home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / kermit / b / ckocon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-30  |  78.1 KB  |  3,095 lines

  1. char *connv = "OS/2 CONNECT command 5A(103), 16 May 93";
  2.  
  3. /* C K O C O N  --  Kermit connect command for OS/2 systems */
  4.  
  5. /*
  6.   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  7.   Columbia University Academic Information Systems, New York City.
  8.  
  9.   Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
  10.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  11.   sold for profit as a software product itself, nor may it be included in or
  12.   distributed with commercial products or otherwise distributed by commercial
  13.   concerns to their clients or customers without written permission of the
  14.   Office of Kermit Development and Distribution, Columbia University.  This
  15.   copyright notice must not be removed, altered, or obscured.
  16.  
  17.   Originally adapted to OS/2 by Chris Adie (C.Adie@uk.ac.edinburgh), 1988.
  18.   VT terminal emulator originally by Chris Adie, 1988 ("If the code looks
  19.   a bit funny sometimes, it's because it was machine translated to C.")
  20.  
  21.   Many changes for 5A by Kai Uwe Rommel (rommel@informatik.tu-muenchen.de),
  22.   1992-93.
  23.  
  24.   And more by Frank da Cruz (fdc@columbia.edu), mostly bug fixes (tabs,
  25.   cursor/attributes save/restore, keypad modes, etc), hooking into new
  26.   SET TERMINAL commands, TCP/IP TELNET support, and cosmetic, 1992-93.
  27. */
  28.  
  29. /*
  30.  *
  31.  * =============================#includes=====================================
  32.  */
  33.  
  34. #include "ckcdeb.h"        /* Typedefs, debug formats, etc */
  35. #include "ckcker.h"        /* Kermit definitions */
  36. #include "ckcasc.h"             /* ASCII character symbols */
  37. #include "ckcxla.h"        /* Character set translation */
  38. #include "ckcnet.h"             /* Network support */
  39. #include "ckuusr.h"        /* For terminal type definitions, etc. */
  40.  
  41. #include <ctype.h>        /* Character types */
  42. #include <io.h>            /* File io function declarations */
  43. #include <process.h>        /* Process-control function declarations */
  44. #include <stdlib.h>        /* Standard library declarations */
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <assert.h>
  50.  
  51. #ifndef __32BIT__
  52. #define far _far
  53. #define near _near
  54. #define pascal _pascal
  55. #endif
  56. #define    INCL_NOPM
  57. #define    INCL_VIO
  58. #define    INCL_DOSPROCESS
  59. #define    INCL_DOSSEMAPHORES
  60. #include <os2.h>
  61. #undef COMMENT
  62.  
  63. #ifndef min
  64. #define min(a,b) ((a) <= (b) ? (a) : (b))
  65. #endif
  66.  
  67. /*
  68.  *
  69.  * =============================#defines======================================
  70.  */
  71.  
  72. #ifdef TRUE
  73. #undef TRUE
  74. #endif /* TRUE */
  75. #define TRUE 1
  76.  
  77. #ifdef FALSE
  78. #undef FALSE
  79. #endif /* FALSE */
  80. #define FALSE 0
  81.  
  82. #define    UPWARD        6
  83. #define    DOWNWARD    7
  84. #define    LBUFSIZE    paginginfo.bufsize
  85.      /* Number of lines in extended buffer (was a constant previosly) */
  86.  
  87. #define DEFTABS        \
  88. "0T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000\
  89. T0000000T0000000T0000000T0000000T0000000T0000000T0000000T000";
  90.  
  91. /*
  92.  *
  93.  * =============================typedefs======================================
  94.  */
  95.  
  96. typedef char    fulstring[256];
  97. typedef int     bool;
  98.  
  99. typedef struct ascreen_rec {    /* Structure for saving screen info */
  100.     unsigned char   ox;
  101.     unsigned char   oy;
  102.     unsigned char   att;
  103.     char            *scrncpy;
  104. } ascreen;
  105.  
  106. /*
  107.  *
  108.  * =============================externals=====================================
  109.  */
  110.  
  111. extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR);  /* Character set xlate */
  112. extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR);  /* functions. */
  113. extern int language;        /* Current language. */
  114. extern struct langinfo langs[];    /* Language info. */
  115. extern struct csinfo fcsinfo[]; /* File character set info */
  116. extern int tcsr, tcsl;        /* Terminal character sets, remote & local. */
  117.  
  118. extern int tnlm, tn_nlm;    /* Terminal newline mode, ditto for TELNET */
  119. extern int tt_crd;        /* Carriage-return display mode */
  120. extern long    speed;
  121. extern int      local, escape, duplex, parity, flow, seslog, sessft,
  122.                 cmdmsk, cmask, sosi, xitsta, debses, mdmtyp, carrier;
  123.  
  124. extern int      network, nettype, ttnproto;
  125.  
  126. extern KEY     *keymap;
  127. extern MACRO     *macrotab;
  128. extern char     ttname[], sesfil[];
  129. extern void    cc_trap();
  130.  
  131. /*
  132.  *
  133.  * =============================variables==============================
  134.  */
  135.  
  136. #ifdef MONO
  137. int     colornormal     = 0x07;
  138. int     colorunderline  = 0x01;
  139. int     colorreverse    = 0x70;
  140. int     colorstatus     = 0x70;
  141. int     colorhelp       = 0x70;
  142. #else
  143. int     colornormal     = 0x30;
  144. int     colorunderline  = 0x3E;
  145. int     colorreverse    = 0x70;
  146. int     colorstatus     = 0x74;
  147. int     colorhelp       = 0x27;
  148. #endif
  149. int    colorcmd;
  150. int     scrninitialised;
  151.  
  152. static long    twochartimes;
  153. static char    termessage[132];
  154. static FILE    *lst = NULL;
  155. static bool     lstclosed = TRUE;
  156. static int      xsize = -1, ysize = -1;
  157. static ascreen  vt100screen, commandscreen, savedscreen;
  158. static unsigned char
  159.   attribute = NUL,
  160.   savedattribute = NUL,
  161.   defaultattribute = NUL;
  162.  
  163. static struct {
  164.     unsigned        reversed:1;
  165.     unsigned        blinking:1;
  166.     unsigned        underlined:1;
  167.     unsigned        bold:1;
  168.     unsigned        invisible:1;
  169. } attrib, savedattrib;
  170.  
  171. static struct paging_record {
  172.     int numlines;    /* no. of lines in extended display buffer */
  173.     int topline;
  174.     int botline;
  175.     char *buffer;
  176.     int bufsize;
  177. } paginginfo;
  178.  
  179. static int wherex;            /* X-coordinate, 1-based */
  180. static int wherey;            /* Y-coordinate, 1-based */
  181. static int margintop = 1;        /* Top of scrolling region */
  182. static int marginbot = 24;        /* Bottom of scrolling region */
  183.  
  184. static int      active, quitnow, hangnow, inshift, outshift, tcs, langsv;
  185.  
  186. static char    answerback[81] = "OS/2 C-Kermit\n";
  187. static char     usertext[(132) + 1];
  188. static char     exittext[(20) + 1];
  189. static char     helptext[(20) + 1];
  190. static char     filetext[(20) + 1];
  191. static char     hostname[(20) + 1];
  192.  
  193. static unsigned char graphicset[32] = {
  194.     0x20, 0x04, 0xB0, 0x1A, 0x17, 0x1B, 0x19, 0xF8,
  195.     0xF1, 0x15, 0x12, 0xD9, 0xBF, 0xDA, 0xC0, 0xC5,
  196.     0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC3, 0xB4, 0xC1,
  197.     0xC2, 0xB3, 0xF3, 0xF2, 0xE3, 0x9D, 0x9C, 0xFA
  198. };
  199.  
  200. static char     htab[133] = DEFTABS    /* Default tab settings */
  201.  
  202. static VIOCURSORINFO crsr_command;
  203. static VIOCURSORINFO crsr_info;
  204.  
  205. static int      row = 0;
  206. static int      column = 0;
  207. static int      achar;
  208.  
  209. static unsigned char g0 = 'B';
  210. static unsigned char g1 = 'B';
  211. static unsigned char *g0g1 = &g0;
  212.  
  213. static bool     printon        = FALSE;    /* Printer is on */
  214. static bool     turnonprinter  = FALSE;    /* Time to turn on printer */
  215. static bool     turnoffprinter = FALSE;    /* Time to turn it off */
  216.  
  217. static bool     wrapit;
  218. static bool     literal   = FALSE;
  219. static bool     screenon  = TRUE;
  220. static bool     cursoron  = TRUE;    /* For speed, turn off when busy */
  221. static bool     relcursor = FALSE;
  222. static bool     keylock   = FALSE;
  223. static bool     vt52graphics = FALSE;
  224.  
  225. static unsigned char saveg0, saveg1, *saveg0g1;
  226. static bool     saverelcursor, saved=FALSE;
  227.  
  228. static bool     dwl[60];
  229. static bool     dwls = FALSE;    /* For optimisation */
  230. static bool     deccolm = FALSE;
  231. static bool     decscnm = FALSE;
  232. static bool     linemode = FALSE;
  233. static bool     insertmode = FALSE;
  234. /*
  235.   Terminal parameters that can also be set externally by SET commands.
  236.   Formerly they were declared and initialized here, and had different
  237.   names, as shown in the comments.  Now they are declared and
  238.   initialized in ckuus7.c.  - fdc
  239. */
  240. extern int tt_arrow;            /* cursorkey  = TRUE; */
  241. extern int tt_keypad;            /* keypadnum  = FALSE; */
  242. extern int tt_wrap;            /* autowrap   = TRUE; */
  243. extern int tt_type;            /* ansi       = TRUE; */
  244. extern int tt_cursor;            /* cursormode = 0; */
  245. extern int tt_answer;            /* answerback = TRUE; */
  246. extern int tt_scrsize;            /* screensize */
  247.  
  248. /* Escape-sequence processing buffer */
  249.  
  250. static bool     escaping = FALSE;
  251. static int      escnext = 1;
  252. static int      esclast = 0;
  253. static unsigned char escbuffer[129];
  254.  
  255. static unsigned char sgrcols[8] = {0, 4, 2, 6, 1, 5, 3, 7};
  256.  
  257. /* Function prototypes */
  258.  
  259. static CHAR (*sxo)(CHAR); /* Local translation functions */
  260. static CHAR (*rxo)(CHAR); /* for output (sending) terminal chars */
  261. static CHAR (*sxi)(CHAR); /* and for input (receiving) terminal chars. */
  262. static CHAR (*rxi)(CHAR);
  263.  
  264. int ttoci(char c);
  265. int line25(void);
  266. int lgotoxy(int x, int y);
  267. int scroll(int updown, int top, int bottom, int nlines);
  268. int clearscreen(int all, int attr);
  269. int setmargins(int top, int bot);
  270. int sendstr(char *s);
  271. int wrtch(char ch);
  272. int bleep(void);
  273. int movetoscreen(char *source, int x, int y, int len);
  274. int savescreen(ascreen *scrn);
  275. int restorescreen(ascreen *scrn);
  276. int clrtoeoln(void);
  277. int killcursor(void);
  278. int newcursor(void);
  279. int cwrite(unsigned char ch);
  280. int toplinetocyclicbuffer(void);
  281. int setcursormode(void);
  282. int restorecursormode(void);
  283.  
  284. extern int concooked(void);
  285. extern int conraw(void);
  286. extern int xxesc(char **);
  287.  
  288. /* thread stuff */
  289. #ifdef __32BIT__
  290. HEV threadsem;
  291. ULONG semcount;
  292. #define THRDSTKSIZ    8192
  293. #else
  294. static long int threadsem;    /* Semaphore to show thread is running */
  295. #define THRDSTKSIZ    2048
  296. static char            stack[THRDSTKSIZ];    /* Stack for second thread */
  297. #endif
  298. static TID             threadid;
  299.  
  300. /* skip escape sequences */
  301.  
  302. /* for comments, see ckucon.c, where this code is copied from */
  303.  
  304. #define ES_NORMAL 0            /* Normal, not in escape sequence */
  305. #define ES_GOTESC 1            /* Current character is ESC */
  306. #define ES_ESCSEQ 2            /* Inside an escape sequence */
  307. #define ES_GOTCSI 3            /* Inside a control sequence */
  308. #define ES_STRING 4            /* Inside DCS,OSC,PM, or APC string */
  309. #define ES_TERMIN 5            /* 1st char of string terminator */
  310.  
  311. static int
  312.   iskipesc = 0,                /* Skip over ANSI escape sequences */
  313.   oskipesc = 0,
  314.   inesc = ES_NORMAL,            /* State of sequence recognizer */
  315.   outesc = ES_NORMAL;
  316.  
  317. int
  318. chkaes(int esc, char c) {
  319.     if (c == CAN || c == SUB)        /* CAN and SUB cancel any sequence */
  320.       esc = ES_NORMAL;
  321.     else                /* Otherwise */
  322.       switch (esc) {            /* enter state switcher */
  323.  
  324.     case ES_NORMAL:            /* NORMAL state */
  325.       if (c == ESC)            /* Got an ESC */
  326.         esc = ES_GOTESC;        /* Change state to GOTESC */
  327.       break;            /* Otherwise stay in NORMAL state */
  328.  
  329.     case ES_GOTESC:            /* GOTESC state */
  330.       if (c == '[')            /* Left bracket after ESC is CSI */
  331.         esc = ES_GOTCSI;        /* Change to GOTCSI state */
  332.       else if (c > 057 && c < 0177)    /* Final character '0' thru '~' */
  333.         esc = ES_NORMAL;        /* Back to normal */
  334.       else if (c == 'P' || (c > 0134 && c < 0140)) /* P, [, ^, or _ */
  335.         esc = ES_STRING;        /* Switch to STRING-absorption state */
  336.       else if (c != ESC)        /* ESC in an escape sequence... */
  337.         esc = ES_ESCSEQ;        /* starts a new escape sequence */
  338.       break;            /* Intermediate or ignored ctrl char */
  339.  
  340.     case ES_ESCSEQ:            /* ESCSEQ -- in an escape sequence */
  341.       if (c > 057 && c < 0177)    /* Final character '0' thru '~' */
  342.         esc = ES_NORMAL;        /* Return to NORMAL state. */
  343.       else if (c == ESC)        /* ESC ... */
  344.         esc = ES_GOTESC;        /* starts a new escape sequence */
  345.       break;            /* Intermediate or ignored ctrl char */
  346.  
  347.     case ES_GOTCSI:            /* GOTCSI -- In a control sequence */
  348.       if (c > 077 && c < 0177)    /* Final character '@' thru '~' */
  349.         esc = ES_NORMAL;        /* Return to NORMAL. */
  350.       else if (c == ESC)        /* ESC ... */
  351.         esc = ES_GOTESC;        /* starts over. */
  352.       break;            /* Intermediate or ignored ctrl char */
  353.  
  354.     case ES_STRING:            /* Inside a string */
  355.       if (c == ESC)            /* ESC may be 1st char of terminator */
  356.         esc = ES_TERMIN;        /* Go see. */
  357.       break;            /* Absorb all other characters. */
  358.  
  359.     case ES_TERMIN:            /* May have a string terminator */
  360.       if (c == '\\')        /* which must be backslash */
  361.         esc = ES_NORMAL;        /* If so, back to NORMAL */
  362.       else                /* Otherwise */
  363.         esc = ES_STRING;        /* Back to string absorption. */
  364.       }
  365.     return(esc);
  366. }
  367.  
  368. /* end code to skip escape sequences */
  369.  
  370. /*
  371.  * Send a character to the serial line in immediate mode, checking to avoid
  372.  * overwriting a character already waiting to be sent.
  373.  */
  374. sendchar(unsigned char c) {
  375.     int i=0;
  376.     while (ttoci(dopar(c))<0 && i++<10)
  377.       DosSleep(twochartimes);
  378.     if (i>=10) {
  379.     active = FALSE;
  380.     strcpy(termessage,network ? "Cannot transmit to network link.\n"
  381.            : "Cannot transmit to serial port.\n");
  382.     }
  383. }
  384.  
  385. /* ------------------------------------------------------------------ */
  386. /* ipadl25 -                                                          */
  387. /* ------------------------------------------------------------------ */
  388. ipadl25() {
  389.     int i, j, n;
  390.     char *s;
  391.     if (tt_type == TT_VT102)
  392.       strcpy(usertext, " C-Kermit VT-102");
  393.     else if (tt_type == TT_VT52)
  394.       strcpy(usertext, " C-Kermit VT-52");
  395.     else strcpy(usertext, " C-Kermit");
  396.     if ( !network )
  397.       sprintf(filetext, "Async %ld", speed);
  398.     else
  399.       switch ( nettype ) {
  400.       case NET_DEC:
  401.         switch ( ttnproto ) {
  402.         case NP_LAT:
  403.           strcpy(filetext, "DECnet LAT");
  404.           break;
  405.         case NP_CTERM:
  406.           strcpy(filetext, "DECnet CTERM");
  407.           break;
  408.         default:
  409.           strcpy(filetext, "DECnet");
  410.           break;
  411.         }
  412.         break;
  413.       case NET_TCPB:
  414.         switch ( ttnproto ) {
  415.         case NP_TELNET:
  416.           strcpy(filetext, "TCP/IP Telnet");
  417.           break;
  418.         default:
  419.           strcpy(filetext, "TCP/IP");
  420.           break;
  421.         }
  422.         break;
  423.       case NET_PIPE:
  424.         strcpy(filetext, "Named Pipe");
  425.         break;
  426.       }
  427.     strcpy(helptext, "Help: Alt-?");
  428.     strcpy(exittext, "Return: Alt-X");
  429.     strcpy(hostname, ttname);
  430.     if (!network)
  431.       strupr(hostname);
  432.     line25();
  433. }
  434.  
  435. /* ------------------------------------------------------------------ */
  436. /* CursorUp -                                                         */
  437. /* ------------------------------------------------------------------ */
  438. static void
  439. cursorup() {
  440.     if ((relcursor ? margintop : 1) != wherey)
  441.     lgotoxy(wherex, wherey - 1);
  442. }
  443.  
  444. /* ------------------------------------------------------------------ */
  445. /* CursorDown -                                                       */
  446. /* ------------------------------------------------------------------ */
  447. static void
  448. cursordown() {
  449.     if ((relcursor ? marginbot : ysize) != wherey)
  450.     lgotoxy(wherex, wherey + 1);
  451. }
  452.  
  453. /* ------------------------------------------------------------------ */
  454. /* CursorRight -                                                      */
  455. /* ------------------------------------------------------------------ */
  456. static void
  457. cursorright() {
  458.     if (wherex < (dwl[wherey - 1] ? xsize - 1 : xsize))
  459.     lgotoxy(wherex + 1, wherey);
  460. }
  461.  
  462. /* ------------------------------------------------------------------ */
  463. /* CursorLeft -                                                       */
  464. /* ------------------------------------------------------------------ */
  465. static void
  466. cursorleft() {
  467.     if (wherex > 1)
  468.     lgotoxy(wherex - 1, wherey);
  469. }
  470.  
  471. /* ------------------------------------------------------------------ */
  472. /* ReverseScreen                              */
  473. /* ------------------------------------------------------------------ */
  474. static void
  475. reversescreen() {
  476.     unsigned char   back;
  477.     unsigned char   fore;
  478.     int             i, r, c;
  479.     USHORT          n;
  480.     unsigned char   cell[132 * 2];
  481.  
  482.     n = sizeof(cell);
  483.     for (r = 0; r < ysize; r++) {    /* flip row */
  484.     VioReadCellStr(cell, &n, r, 0, 0);
  485.     for (c = 1; c < n; c += 2) {    /* do each cell in row */
  486.         back = (cell[c] & 0x70) >> 4;
  487.         fore = (cell[c] & 0x07);
  488.         if (cell[c] == colorunderline)
  489.         cell[c] ^= 0x70;
  490.         else
  491.         cell[c] = (cell[c] & 0x88) | fore << 4 | back;
  492.     }
  493.     VioWrtCellStr(cell, n, r, 0, 0);
  494.     }
  495. }
  496.  
  497. /* ----------------------------------------------------------------- */
  498. /* ClrScreen -                                                       */
  499. /* ----------------------------------------------------------------- */
  500. static void
  501. clrscreen() {
  502.     int             i, j;
  503.     int             nlines;
  504.     USHORT          n;
  505.     char            cells[132 * 2];
  506.  
  507.     /* copy lines on screen to extended display buffer */
  508.     n = xsize * 2;
  509.     for (i = ysize - 1; i >= 0; i--) {
  510.     VioReadCellStr((char *) cells, &n, i, 0, 0);
  511.     for (j = 0; j < xsize; j++) {
  512.         if (cells[j * 2] != ' ')
  513.         break;
  514.     }
  515.     if (j < xsize)
  516.         break;
  517.     }
  518.     nlines = i;            /* no. of nonblank lines-1 */
  519.     for (i = 0; i <= nlines; ++i) {
  520.     paginginfo.botline = (paginginfo.botline + 1) % LBUFSIZE;
  521.     if (paginginfo.numlines < LBUFSIZE)
  522.         paginginfo.numlines++;
  523.     else
  524.         paginginfo.topline = (paginginfo.topline + 1) % LBUFSIZE;
  525.     VioReadCellStr((paginginfo.buffer + xsize * 2 * paginginfo.botline),
  526.                &n, i, 0, 0);
  527.     }
  528.     for (i = 0; i < ysize; i++)
  529.     dwl[i] = FALSE;
  530.     dwls = FALSE;
  531.     clearscreen(0, attribute);
  532. }
  533.  
  534. static void
  535. readmchar_escape() {
  536.     /* Stores character in achar directly */
  537.     if (escnext <= esclast) {
  538.     achar = escbuffer[escnext];
  539.     escnext = escnext + 1;
  540.     } else
  541.     achar = 0;
  542. }
  543.  
  544. static int
  545. pnumber(int *achar) {
  546.     int num = 0;
  547.  
  548.     while (isdigit(*achar)) {    /* get number */
  549.     num = (num * 10) + (*achar) - 48;
  550.     readmchar_escape();
  551.     }
  552.     return (num);
  553. }
  554.  
  555. static void
  556. clreoscr_escape() {
  557.     char cell[2];
  558.     int i;
  559.  
  560.     if (wherex == 1 && wherey == 1) {
  561.     clrscreen();
  562.     return;
  563.     }
  564.     cell[0] = ' ';
  565.     cell[1] = attribute;
  566.     i = (xsize * ysize) - (((wherey - 1) * xsize) + (wherex - 1));
  567.     VioWrtNCell(cell, i, wherey - 1, wherex - 1, 0);
  568.     for (i = wherey - 1; i < ysize; i++)
  569.     dwl[i] = FALSE;
  570.     dwls = FALSE;
  571.     for (i = 0; i < ysize; i++)
  572.     if (dwl[i]) {
  573.         dwls = TRUE;
  574.         break;
  575.     }
  576. }
  577.  
  578. static void
  579. clrboscr_escape() {
  580.     char cell[2];
  581.     int i;
  582.  
  583.     cell[0] = ' ';
  584.     cell[1] = attribute;
  585.     i = ((wherey - 1) * xsize) + wherex;
  586.     VioWrtNCell(cell, i, 0, 0, 0);
  587.     for (i = 0; i < wherey; i++)
  588.     dwl[i] = FALSE;
  589.     dwls = FALSE;
  590.     for (i = 0; i < ysize; i++)
  591.     if (dwl[i]) {
  592.         dwls = TRUE;
  593.         break;
  594.     }
  595. }
  596.  
  597. static void
  598. clrbol_escape() {
  599.     char cell[2];
  600.  
  601.     cell[0] = ' ';
  602.     cell[1] = attribute;
  603.     VioWrtNCell(cell, wherex, wherey - 1, 0, 0);
  604. }
  605.  
  606. static void
  607. clrline_escape() {
  608.     char cell[2];
  609.  
  610.     cell[0] = ' ';
  611.     cell[1] = attribute;
  612.     VioWrtNCell(cell, xsize, wherey - 1, 0, 0);
  613. }
  614.  
  615. static void
  616. decdwl_escape(bool dwlflag) {
  617.     unsigned char   linenumber;
  618.     unsigned char   newx;
  619.     char            cells[132 * 2];
  620.     int             i;
  621.     USHORT          n;
  622.     /* Decdwl */
  623.     linenumber = wherey - 1;
  624.     if (dwlflag != dwl[linenumber]) {
  625.     /* change size */
  626.     n = xsize * 2;
  627.     VioReadCellStr((char *) cells, &n, linenumber, 0, 0);
  628.     if (dwlflag) {        /* make this line double size */
  629.         for (i = xsize / 2 - 1; i >= 0; --i) {    /* expand */
  630.         cells[4 * i] = cells[2 *i];
  631.         cells[4 * i + 2] = ' ';
  632.         }
  633.         newx = (wherex - 1) * 2 + 1;
  634.         dwls = TRUE;
  635.     } else {        /* make this line single size */
  636.         for (i = 0; i <= xsize / 2 - 1; ++i)
  637.         cells[2 * i] = cells[4 * i];
  638.         for (i = xsize / 2; i < xsize; ++i)
  639.         cells[2 * i] = ' ';
  640.         newx = (wherex - 1) / 2 + 1;
  641.         dwls = FALSE;
  642.         for (i = 0; i < ysize; i++)
  643.         if (dwl[i]) {
  644.             dwls = TRUE;
  645.             break;
  646.         }
  647.     }
  648.     VioWrtCellStr((char *) cells, n, linenumber, 0, 0);
  649.     dwl[linenumber] = dwlflag;
  650.     if (newx >= xsize)
  651.       newx = xsize - 1;
  652.     lgotoxy(newx, wherey);
  653.     }
  654. }
  655.  
  656. static void                /* Reset the terminal emulator */
  657. doreset() {
  658.     int i;
  659.     defaultattribute = colornormal;
  660.     attribute = defaultattribute;
  661.     attrib.blinking = FALSE;
  662.     attrib.bold = FALSE;
  663.     attrib.invisible = FALSE;
  664.     attrib.underlined = FALSE;
  665.     attrib.reversed = FALSE;
  666.     g0 = g1 = 'A';
  667.     g0g1 = &g0;
  668.     printon = FALSE;
  669.     screenon = TRUE;
  670.     vt52graphics = FALSE;
  671.     saved = FALSE;
  672.     linemode = FALSE;
  673.     insertmode = FALSE;
  674.     tt_arrow = TRUE;
  675.     tt_keypad = FALSE;
  676.     tt_wrap = TRUE;
  677.     tt_type = TT_VT102;
  678.     keylock = FALSE;
  679.     deccolm = decscnm = FALSE;
  680.     for (i = 0; i < ysize; i++)
  681.       dwl[i] = FALSE;
  682.     dwls = FALSE;
  683.     for (i = 1; i < xsize; i++)
  684.       htab[i] = (i % 8) == 1 ? 'T' : '0'; /* was "== 0" */
  685.     relcursor = FALSE;
  686.     setmargins(1, ysize);
  687.     clrscreen();
  688. }
  689.  
  690.  
  691. static void
  692. vtescape() {
  693.     unsigned char   j;
  694.     unsigned char   k;
  695.     unsigned char   l;
  696.     unsigned char   blankcell[2];
  697.     int             i;
  698.     int             pn[11];
  699.     bool            private;
  700.     char            tempstr[20];
  701.     int             fore, back;
  702.     escaping = FALSE;
  703.     escnext = 1;
  704.     readmchar_escape();
  705.     if (screenon || (achar == '[')) {
  706.     /* screen escape sequences  */
  707.     switch (achar) {        /* First Level */
  708.     case '[':
  709.         {                /* Left square bracket */
  710.         readmchar_escape();
  711.         switch (achar) {    /* Second level */
  712.         case 'A':
  713.             cursorup();
  714.             wrapit = FALSE;
  715.             break;
  716.         case 'B':
  717.             cursordown();
  718.             wrapit = FALSE;
  719.             break;
  720.         case 'C':
  721.             cursorright();
  722.             if (dwl[wherey - 1])
  723.               cursorright();
  724.             break;
  725.         case 'D':
  726.             cursorleft();
  727.             if (dwl[wherey - 1])
  728.               cursorleft();
  729.             break;
  730.         case 'J':    /* Erase End of Display */
  731.             clreoscr_escape();
  732.             break;
  733.         case 'K':
  734.             clrtoeoln();
  735.             break;
  736.         case '?':
  737.             private = TRUE;
  738.             readmchar_escape();
  739.             goto LB2001;
  740.         case 'f':
  741.         case 'H':    /* Cursor Home */
  742.             lgotoxy(1, relcursor ? margintop : 1);
  743.             break;
  744.         case 'g':    /* Tab Clear at this position */
  745.             htab[wherex] = '0';
  746.             break;
  747.         case '}':
  748.         case 'm':    /* Normal Video - Exit all attribute modes */
  749.             attribute = defaultattribute;
  750.             attrib.blinking = FALSE;
  751.             attrib.bold = FALSE;
  752.             attrib.invisible = FALSE;
  753.             attrib.underlined = FALSE;
  754.             attrib.reversed = FALSE;
  755.             break;
  756.         case 'r':    /* Reset Margin */
  757.             setmargins(1, ysize);
  758.             lgotoxy(1, 1);
  759.             break;
  760.         case 'c':
  761.         case 'h':
  762.         case 'l':
  763.         case 'n':
  764.         case 'x':
  765.             pn[1] = 0;
  766.             private = FALSE;
  767.             k = 1;
  768.             goto LB2003;
  769.         case ';':
  770.             pn[1] = 0;
  771.             private = FALSE;
  772.             k = 1;
  773.             goto LB2002;
  774.         case 'L':
  775.         case 'M':
  776.         case '@':
  777.         case 'P':
  778.             pn[1] = 1;
  779.             private = FALSE;
  780.             k = 1;
  781.             goto LB2002;
  782.         default:    /* Pn - got a number */
  783.             private = FALSE;
  784.         LB2001:
  785.             {        /* Esc [ Pn...Pn x   functions */
  786.             pn[1] = pnumber(&achar);
  787.             k = 1;
  788.         LB2002:
  789.             while (achar == ';') {    /* get Pn[k] */
  790.                 readmchar_escape();
  791.                 k++;
  792.                 if (achar == '?') {
  793.                 readmchar_escape();
  794.                 }
  795.                 pn[k] = pnumber(&achar);
  796.             }
  797.             pn[k + 1] = 1;
  798.         LB2003:
  799.             switch (achar) { /* Third level */
  800.             case 'A':
  801.                 do {
  802.                 cursorup();
  803.                 wrapit = FALSE;
  804.                 pn[1] = pn[1] - 1;
  805.                 }
  806.                 while (!(pn[1] <= 0));
  807.                 break;
  808.             case 'B':
  809.                 do {
  810.                 cursordown();
  811.                 wrapit = FALSE;
  812.                 pn[1] = pn[1] - 1;
  813.                 }
  814.                 while (!(pn[1] <= 0));
  815.                 break;
  816.             case 'C':
  817.                 do {
  818.                 cursorright();
  819.                 if (dwl[wherey - 1])
  820.                     cursorright();
  821.                 pn[1] = pn[1] - 1;
  822.                 }
  823.                 while (pn[1] > 0);
  824.                 break;
  825.             case 'D':
  826.                 do {
  827.                 cursorleft();
  828.                 if (dwl[wherey - 1])
  829.                     cursorleft();
  830.                 pn[1] = pn[1] - 1;
  831.                 } while (pn[1] > 0);
  832.                 break;
  833.             case 'f':
  834.             case 'H':
  835.                 /* Direct cursor address */
  836.                 if (pn[1] == 0)
  837.                 pn[1] = 1;
  838.                 if (relcursor)
  839.                 pn[1] += margintop - 1;
  840.                 if (pn[1] > ysize)
  841.                     pn[1] = ysize;
  842.                 if (pn[2] == 0)
  843.                 pn[2] = 1;
  844.                 if (dwl[pn[1] - 1]) {
  845.                 pn[2] = 2 * pn[2] - 1;
  846.                 if (pn[2] > xsize)
  847.                     pn[2] = xsize - 1;
  848.                 } else if (pn[2] > xsize)
  849.                 pn[2] = xsize;
  850.                 wrapit = FALSE;
  851.                 lgotoxy(pn[2], pn[1]);
  852.                 break;
  853.             case 'c':    /* Device Attributes */
  854.                 if (pn[1] == 0)
  855.                 sendstr("[?6c");
  856.                 break;
  857.             case 'g':
  858.                 if (pn[1] == 3) {
  859.                 /* clear all tabs */
  860.                 for (j = 1; j <=xsize; ++j)
  861.                     htab[j] = '0';
  862.                 } else if (pn[1] == 0)
  863.                 /* clear tab at current position */
  864.                 htab[wherex] = '0';
  865.                 break;
  866.             case 'h':    /* Set Mode */
  867.                 for (j = 1; j <= k; ++j)
  868.                 if (private)
  869.                     switch (pn[j]) {    /* Field specs */
  870.                     case 1:    /* DECCKM  */
  871.                     tt_arrow = TRUE;
  872.                     break;
  873.                     case 2:    /* DECANM : ANSI/VT52 */
  874.                     tt_type = TT_VT102;
  875.                     vt52graphics = FALSE;
  876.                     break;
  877.                     case 3:    /* DECCOLM : Col = 132 */
  878.                     deccolm = TRUE;
  879.                     clrscreen();
  880.                     break;
  881.                     case 4:    /* DECSCLM */
  882.                     break;
  883.                     case 5:    /* DECSCNM */
  884.                     if (decscnm)
  885.                         break;    /* Already set */
  886.                     decscnm = TRUE;
  887.                     reversescreen();
  888.                     defaultattribute = colornormal;
  889.                     attribute = defaultattribute;
  890.                     if (attrib.underlined)
  891.                         attribute = colorunderline;
  892.                     if (attrib.reversed) {
  893.                         attribute = colorreverse;
  894.                         if (attrib.underlined)
  895.                         attribute = colorunderline &
  896.                           0x0F | colorreverse & 0xF0;
  897.                     }
  898.                     if (attrib.blinking)
  899.                         attribute |= 0x80;
  900.                     if (attrib.bold)
  901.                         attribute ^= 8;
  902.                     if (attrib.invisible) {
  903.                         i = (attribute & 0xF8);
  904.                         attribute = i | ((i >> 4) & 7);
  905.                     }
  906.                     break;
  907.                     case 6:    /* DECOM : Relative origin */
  908.                     relcursor = TRUE;
  909.                     lgotoxy(1, margintop);
  910.                     break;
  911.                     case 7:    /* DECAWM */
  912.                     tt_wrap = TRUE;
  913.                     break;
  914.                     case 8:    /* DECARM */
  915.                     break;
  916.                     case 9:    /* DECINLM */
  917.                     break;
  918.                     default:
  919.                     break;
  920.                 } else
  921.                     switch (pn[j]) {
  922.                     case 2:    /* Keyboard locked */
  923.                     keylock = TRUE;
  924.                     break;
  925.                     case 4:    /* Ansi insert mode */
  926.                     insertmode = TRUE;
  927.                     break;
  928.                     case 20:    /* Ansi linefeed mode */
  929.                     linemode = TRUE;
  930.                     break;
  931.                     default:
  932.                     break;
  933.                     }
  934.                 break;
  935.             case 'l':    /* Reset Mode */
  936.                 for (j = 1; j <= k; ++j)
  937.                 if (private)
  938.                     switch ((pn[j])) {    /* Field specs */
  939.                     case 1:    /* DECCKM  */
  940.                     tt_arrow = FALSE;
  941.                     break;
  942.                     case 2:    /* DECANM : ANSI/VT52 */
  943.                     tt_type = TT_VT52;
  944.                     vt52graphics = FALSE;
  945.                     break;
  946.                     case 3:    /* DECCOLM : 80 col */
  947.                     deccolm = FALSE;
  948.                     clrscreen();
  949.                     break;
  950.                     case 4:    /* DECSCLM */
  951.                     break;
  952.                     case 5:    /* DECSCNM */
  953.                     if (!decscnm)
  954.                         break;
  955.                     decscnm = !decscnm;
  956.                     reversescreen();
  957.                     defaultattribute = colornormal;
  958.                     attribute = defaultattribute;
  959.                     if (attrib.underlined)
  960.                         attribute = colorunderline;
  961.                     if (attrib.reversed) {
  962.                         attribute = colorreverse;
  963.                         if (attrib.underlined)
  964.                         attribute = colorunderline &
  965.                           0x0F | colorreverse & 0xF0;
  966.                     }
  967.                     if (attrib.blinking)
  968.                         attribute |= 0x80;
  969.                     if (attrib.bold)
  970.                         attribute ^= 8;
  971.                     if (attrib.invisible) {
  972.                         i = (attribute & 0xF8);
  973.                         attribute = i | ((i >> 4) & 7);
  974.                     }
  975.                     break;
  976.                     case 6:    /* DECOM : Relative origin */
  977.                     relcursor = FALSE;
  978.                     lgotoxy(1, 1);
  979.                     break;
  980.                     case 7:    /* DECAWM */
  981.                     tt_wrap = FALSE;
  982.                     break;
  983.                     case 8:    /* DECARM */
  984.                     break;
  985.                     case 9:    /* DECINLM */
  986.                     break;
  987.                     default:
  988.                     break;
  989.                 } else
  990.                     switch (pn[j]) {
  991.                     case 2:    /* Keyboard unlocked */
  992.                     keylock = FALSE;
  993.                     break;
  994.                     case 4:    /* Ansi insert mode */
  995.                     insertmode = FALSE;
  996.                     break;
  997.                     case 20:    /* Ansi linefeed mode */
  998.                     linemode = FALSE;
  999.                     break;
  1000.                     default:
  1001.                     break;
  1002.                     }
  1003.                 break;
  1004.             case 'i':    /* Printer Screen  on / off */
  1005. #ifndef M_I286
  1006. /*
  1007.   Not only does this not work, but it causes crashes ("stack overflow"), in
  1008.   the 16-bit version, at least for me -- but maybe that's because I don't have
  1009.   a printer.  For now, we'll leave it buggy in the 32-bit version and turn it
  1010.   off completely in the 16-bit version.  NEEDS DEBUGGING BY SOMEBODY WHO HAS A
  1011.   PRINTER.
  1012. */
  1013.                 if (pn[1] == 0)
  1014.                   /* Need code here to print whole screen */
  1015.                   break;
  1016.                 else if (pn[1] == 1)
  1017.                   /* Need code here to print current line */
  1018.                   /* But only if private == TRUE */
  1019.                   break;
  1020. /* 
  1021.   For pn = 4 or 5, we should differentiate here between transparent print
  1022.   (private == FALSE) and autoprint (private == TRUE).  As presently coded,
  1023.   we always do transparent print.
  1024. */
  1025.                 else if (pn[1] == 4)
  1026.                   turnoffprinter = TRUE;
  1027.                 else if (pn[1] == 5)
  1028.                   turnonprinter = TRUE;
  1029.  
  1030. /*  6 and 7 are not in the VT102 manual.  Maybe in the Scottish version?  */
  1031.  
  1032.                 else if (pn[1] == 6)
  1033.                   screenon = FALSE;
  1034.                 else if (pn[1] == 7)
  1035.                   screenon = TRUE;
  1036. #endif /* M_I286 */
  1037.                 break;
  1038.             case 'q':        /* Load LEDs */
  1039.                 break;        /* (nothing) */
  1040.             case 'n':
  1041.                 if (pn[1] == 5)     /* Terminal Status Report */
  1042.                   sendstr("[0n");     /* Terminal is OK */
  1043.                 else if (pn[1] == 6) { /* Cursor position report */
  1044. #ifdef M_I286
  1045. /*
  1046.   16-bit version must use a hand-coded in-line version of sprintf to avoid
  1047.   the function call that would crash the program with a stack overflow.
  1048.   Handles numbers 0 - 999.  No range checking.  - fdc
  1049. */
  1050.                 int i = 0, j;
  1051.                 tempstr[i++] = '[';
  1052.                 if ((j = wherey / 100) > 0)
  1053.                   tempstr[i++] = (char) (j + 48);
  1054.                 if ((j = (wherey % 100) / 10) > 0 ||
  1055.                     wherey > 99)
  1056.                   tempstr[i++] = (char) (j + 48);
  1057.                 if ((j = wherey % 10) > 0 ||
  1058.                     wherey > 9)
  1059.                   tempstr[i++] = (char) (j + 48);
  1060.                 tempstr[i++] = ';';
  1061.                 if ((j = wherex / 100) > 0)
  1062.                   tempstr[i++] = (char) (j + 48);
  1063.                 if ((j = (wherex % 100) / 10) > 0 ||
  1064.                     wherex > 99)
  1065.                   tempstr[i++] = (char) (j + 48);
  1066.                 if ((j = wherex % 10) > 0 ||
  1067.                     wherex > 9)
  1068.                   tempstr[i++] = (char) (j + 48);
  1069.                 tempstr[i++] = 'R';
  1070.                 tempstr[i] = '\0';
  1071.                 sendstr(tempstr);
  1072. #else
  1073. /* 32-bit version can call sprintf() here.  This is the original code. */
  1074.                 sendstr("[");
  1075.                 sprintf(tempstr,"%1d",(int) wherey); /* row */
  1076.                 sendchar(tempstr[0]);
  1077.                 if (tempstr[1])
  1078.                     sendchar(tempstr[1]);
  1079.                 sendchar(';');
  1080.                 sprintf(tempstr,"%1d",(int) wherex); /* col */
  1081.                 sendchar(tempstr[0]);
  1082.                 if (tempstr[1])
  1083.                     sendchar(tempstr[1]);
  1084.                 sendchar('R');
  1085. #endif /* M_286 */
  1086.                 }
  1087.                 break;
  1088.             case 'x':    /* Request terminal Parameters */
  1089.                 if (pn[1] > 1)
  1090.                 break;
  1091.                 tempstr[0] = '[';
  1092.                 tempstr[1] = (pn[1] == 0) ? '2' : '3';
  1093.                 tempstr[2] = ';';
  1094.                 switch (parity) {                
  1095.                 case 'e':
  1096.                 tempstr[3] = '5';
  1097.                 tempstr[5] = '2';
  1098.                 break;
  1099.                 case 'o':
  1100.                 tempstr[3] = '4';
  1101.                 tempstr[5] = '2';
  1102.                 break;
  1103.                 case 0:
  1104.                 tempstr[3] = '1';
  1105.                 tempstr[5] = '1';
  1106.                 break;
  1107.                 default:
  1108.                 tempstr[3] = '1';
  1109.                 tempstr[5] = '2';
  1110.                 break;
  1111.                 }
  1112.                 tempstr[4] = ';';
  1113.                 switch (speed) {
  1114.                 case 50:
  1115.                 i = 0;
  1116.                 break;
  1117.                 case 75:
  1118.                 i = 8;
  1119.                 break;
  1120.                 case 110:
  1121.                 i = 16;
  1122.                 break;
  1123.                 case 133:
  1124.                 i = 14;
  1125.                 break;
  1126.                 case 150:
  1127.                 i = 32;
  1128.                 break;
  1129.                 case 200:
  1130.                 i = 40;
  1131.                 break;
  1132.                 case 300:
  1133.                 i = 48;
  1134.                 break;
  1135.                 case 600:
  1136.                 i = 56;
  1137.                 break;
  1138.                 case 1200:
  1139.                 i = 64;
  1140.                 break;
  1141.                 case 1800:
  1142.                 i = 72;
  1143.                 break;
  1144.                 case 2000:
  1145.                 i = 80;
  1146.                 break;
  1147.                 case 2400:
  1148.                 i = 88;
  1149.                 break;
  1150.                 case 3600:
  1151.                 i = 96;
  1152.                 break;
  1153.                 case 4800:
  1154.                 i = 104;
  1155.                 break;
  1156.                 case 9600:
  1157.                 i = 112;
  1158.                 break;
  1159.                 case 19200:
  1160.                 i = 120;
  1161.                 break;
  1162.                 default:
  1163.                 i = 128;
  1164.                 break;
  1165.                 }
  1166. #ifdef M_I286
  1167. /*
  1168.   Hand-coded sprintf() again.  - fdc.
  1169. */
  1170.                 {
  1171.                 int x, j;
  1172.                 x = i;
  1173.                 i = 6;
  1174.                 tempstr[i++] = ';';
  1175.                 if ((j = x / 100) > 0)
  1176.                   tempstr[i++] = (char) (j + 48);
  1177.                 if ((j = (wherey % 100) / 10) > 0 ||
  1178.                     wherey > 99)
  1179.                   tempstr[i++] = (char) (j + 48);
  1180.                 if ((j = wherey % 10) > 0 ||
  1181.                     wherey > 9)
  1182.                   tempstr[i++] = (char) (j + 48);
  1183.                 tempstr[i++] = ';';
  1184.                 if ((j = x / 100) > 0)
  1185.                   tempstr[i++] = (char) (j + 48);
  1186.                 if ((j = (wherey % 100) / 10) > 0 ||
  1187.                     wherey > 99)
  1188.                   tempstr[i++] = (char) (j + 48);
  1189.                 if ((j = wherey % 10) > 0 ||
  1190.                     wherey > 9)
  1191.                   tempstr[i++] = (char) (j + 48);
  1192.                 tempstr[i++] = ';';
  1193.                 tempstr[i++] = '1';
  1194.                 tempstr[i++] = ';';
  1195.                 tempstr[i++] = '0';
  1196.                 tempstr[i++] = 'x';
  1197.                 tempstr[i++] = '\0';
  1198.                 }
  1199. #else
  1200.                 sprintf(&tempstr[6], ";%d;%d;1;0x", i, i);
  1201. #endif /* M_I286 */
  1202.                 sendstr(tempstr);
  1203.                 break;
  1204.             case 'm':    /* Select graphic rendition */
  1205.             case '}':
  1206.                 for (j = 1; j <= k; ++j)
  1207.                 switch ((pn[j])) {    /* Field specs */
  1208.                 case 0:    /* normal */
  1209.                     attribute = defaultattribute;
  1210.                     attrib.blinking = FALSE;
  1211.                     attrib.bold = FALSE;
  1212.                     attrib.invisible = FALSE;
  1213.                     attrib.underlined = FALSE;
  1214.                     attrib.reversed = FALSE;
  1215.                     break;
  1216.                 case 1:    /* bold */
  1217.                     attrib.bold = TRUE;
  1218.                     attribute ^= 8;
  1219.                     break;
  1220.                 case 4:    /* underline */
  1221.                     attrib.underlined = TRUE;
  1222.                     attribute = colorunderline;
  1223.                     break;
  1224.                 case 5:    /* blink */
  1225.                     attrib.blinking = TRUE;
  1226.                     attribute |= 0x80;
  1227.                     break;
  1228.                 case 7:    /* reverse video */
  1229.                     if (attrib.reversed)
  1230.                     break;
  1231.                     attrib.reversed = TRUE;
  1232.                     attribute = colorreverse;
  1233.                     if (attrib.underlined)
  1234.                         attribute = colorunderline &
  1235.                       0x0F |
  1236.                         colorreverse & 0xF0;
  1237.                     if (attrib.invisible)
  1238.                         attribute = attribute &
  1239.                       0xF0 |
  1240.                         (attribute >> 4) & 0x07;
  1241.                     break;
  1242.                 case 8:    /* invisible */
  1243.                     if (attrib.invisible)
  1244.                     break;
  1245.                     attrib.invisible = TRUE;
  1246.                     attribute = attribute &
  1247.                       0xF0 |
  1248.                     (attribute >> 4) & 0x07;
  1249.                     break;
  1250.                 case 30:
  1251.                 case 31:
  1252.                 case 32:
  1253.                 case 33:
  1254.                 case 34:
  1255.                 case 35:
  1256.                 case 36:
  1257.                 case 37:
  1258.                     /* select foreground */
  1259.                     i = (attribute & 0xF8);
  1260.                     attribute = (i | sgrcols[pn[j] - 30]);
  1261.                     break;
  1262.                 case 40:
  1263.                 case 41:
  1264.                 case 42:
  1265.                 case 43:
  1266.                 case 44:
  1267.                 case 45:
  1268.                 case 46:
  1269.                 case 47:
  1270.                     /* select back ground */
  1271.                     i = (attribute & 0x8F);
  1272.                     l = sgrcols[pn[j] - 40];
  1273.                     attribute = (i | ((l << 4)));
  1274.                     break;
  1275.                 default:
  1276.                     break;
  1277.                 }
  1278.                 break;
  1279.             case 'r':    /* set margin */
  1280.                 if ((k < 2) || (pn[2] == 0))
  1281.                 pn[2] = ysize;
  1282.                 if (pn[1] == 0)
  1283.                 pn[1] = 1;
  1284.                 if ((pn[1] > 0) &&
  1285.                 (pn[1] < pn[2]) &&
  1286.                 (pn[2] <= ysize)) {
  1287.                 setmargins(pn[1], pn[2]);
  1288.                 lgotoxy(1, relcursor ? margintop : 1);
  1289.                 }
  1290.                 break;
  1291.             case 'J':
  1292.                 switch ((pn[1])) {
  1293.                 case 0:    /* clear to end of screen */
  1294.                 clreoscr_escape();
  1295.                 break;
  1296.                 case 1:    /* clear to beginning */
  1297.                 clrboscr_escape();
  1298.                 break;
  1299.                 case 2:    /* clear all of screen */
  1300.                 clrscreen();
  1301.                 break;
  1302.                 default:
  1303.                 break;
  1304.                 }
  1305.                 break;
  1306.             case 'K':
  1307.                 switch ((pn[1])) {
  1308.                 case 0:    /* clear to end of line */
  1309.                 clrtoeoln();
  1310.                 break;
  1311.                 case 1:    /* clear to beginning */
  1312.                 clrbol_escape();
  1313.                 break;
  1314.                 case 2:    /* clear line */
  1315.                 clrline_escape();
  1316.                 break;
  1317.                 default:
  1318.                 break;
  1319.                 }
  1320.                 break;
  1321.             case 'L':    /* Insert lines */
  1322.                 for (i = 1; i <= pn[1]; ++i)
  1323.                 scroll(DOWNWARD, wherey - 1, marginbot - 1, 1);
  1324.                 break;
  1325.             case 'M':    /* Delete lines */
  1326.                 for (i = 1; i <= pn[1]; ++i)
  1327.                 scroll(UPWARD, wherey - 1, marginbot - 1, 1);
  1328.                 break;
  1329.             case '@':    /* Insert characters */
  1330.                 blankcell[0] = ' ';
  1331.                 blankcell[1] = attribute;
  1332.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  1333.                 if (pn[1] > xsize + 1 - wherex)
  1334.                 pn[1] = xsize + 1 - wherex;
  1335.                 VioScrollRt(wherey - 1,
  1336.                     wherex - 1,
  1337.                     wherey - 1,
  1338.                     xsize - 1,
  1339.                     pn[1],
  1340.                     blankcell,
  1341.                     0
  1342.                     );
  1343.                 break;
  1344.             case 'P':    /* DeleteChar */
  1345.                 blankcell[0] = ' ';
  1346.                 blankcell[1] = attribute;
  1347.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  1348.                 if (pn[1] > xsize + 1 - wherex)
  1349.                 pn[1] = xsize + 1 - wherex;
  1350.                 VioScrollLf(wherey - 1,
  1351.                     wherex - 1,
  1352.                     wherey - 1,
  1353.                     xsize - 1,
  1354.                     pn[1],
  1355.                     blankcell,
  1356.                     0
  1357.                     );
  1358.                 break;
  1359.             default:
  1360.                 break;
  1361.             }
  1362.             }
  1363.             break;
  1364.         }
  1365.         }            /* Left square bracket */
  1366.         break;
  1367.     case '7':        /* Save cursor position and attributes */
  1368.         saved = TRUE;        /* Remember they are saved */
  1369.         row = wherey;        /* Current row (absolute) */
  1370.         column = wherex;        /* Current column (absolute) */
  1371.         savedattribute = attribute;    /* Current attributes */
  1372.         savedattrib = attrib;    /* Character attributes structure */
  1373.         saverelcursor = relcursor;    /* Cursor addressing mode */
  1374.         saveg0 = g0;        /* Character sets */
  1375.         saveg1 = g1;
  1376.         saveg0g1 = g0g1;
  1377.         break;
  1378.     case '8':        /* Restore Cursor Position and attributes */
  1379.         if (saved == FALSE) {    /* Nothing saved, home the cursor */
  1380.         lgotoxy(1, relcursor ? margintop : 1);
  1381.             break;
  1382.         }
  1383. #ifdef COMMENT
  1384. /*
  1385.   Wrong!  Restoring the saved parameters does not unsave them.  -fdc
  1386. */
  1387.         saved = FALSE;
  1388. #endif /* COMMENT */
  1389.         lgotoxy(column, row);    /* Goto saved position */
  1390.         attribute = savedattribute;    /* Restore saved attributes */
  1391.         attrib = savedattrib;
  1392.         relcursor = saverelcursor;    /* Restore cursor addressing mode */
  1393.         g0 = saveg0;        /* Restore character sets */
  1394.         g1 = saveg1;
  1395.         g0g1 = saveg0g1;
  1396.         break;
  1397.     case 'A':
  1398.         if (tt_type == TT_VT52)    /* VT52 control */
  1399.         cursorup();
  1400.         break;
  1401.     case 'B':
  1402.         if (tt_type == TT_VT52)    /* VT52 control */
  1403.         cursordown();
  1404.         break;
  1405.     case 'C':
  1406.         if (tt_type == TT_VT52)    /* VT52 control */
  1407.         cursorright();
  1408.         break;
  1409.     case 'D':
  1410.         if (tt_type == TT_VT52)    /* VT52 control */
  1411.           cursorleft();
  1412.         else {
  1413.         /* Index */
  1414.         if (wherey == marginbot)
  1415.           scroll(UPWARD, margintop - 1, marginbot - 1, 1);
  1416.         else
  1417.           cursordown();
  1418.         }
  1419.         break;
  1420.     case 'E':            /* Next Line */
  1421.         wrtch(13);
  1422.         wrtch(10);
  1423.         break;
  1424.     case 'F':
  1425.         if (tt_type == TT_VT52)    /* VT52 control */
  1426.         vt52graphics = TRUE;
  1427.         break;
  1428.     case 'G':
  1429.         if (tt_type == TT_VT52)    /* VT52 control */
  1430.         vt52graphics = FALSE;
  1431.         break;
  1432.     case 'H':
  1433.         if (tt_type == TT_VT102) {
  1434.         /* Set Tab Stop */
  1435.         htab[wherex] = 'T';
  1436.         }
  1437.         /* Set Tab Stop */
  1438.         else
  1439.         lgotoxy(1, 1);
  1440.         /* VT52 control */
  1441.         break;
  1442.     case 'I':
  1443.         if (tt_type == TT_VT52) {
  1444.         /* VT52 control */
  1445.         if ((margintop < wherey))
  1446.             cursorup();
  1447.         else
  1448.             scroll(DOWNWARD, margintop - 1, marginbot - 1, 1);
  1449.         }
  1450.         break;
  1451.     case 'J':
  1452.         if (tt_type == TT_VT52)
  1453.         /* VT52 control */
  1454.         clreoscr_escape();
  1455.         break;
  1456.     case 'K':
  1457.         if (tt_type == TT_VT52)
  1458.         /* VT52 control */
  1459.         clrtoeoln();
  1460.         break;
  1461.     case 'M':
  1462.         /* Reverse Index */
  1463.         if (margintop == wherey)    /* "==", not ">="!  - fdc */
  1464.           scroll(DOWNWARD, margintop - 1, marginbot - 1, 1);
  1465.         else
  1466.           cursorup();
  1467.         break;
  1468.     case 'Y':
  1469.         if (tt_type == TT_VT52) {    /* VT52 control */
  1470.         /* direct cursor address */
  1471.         readmchar_escape();
  1472.         row = achar - 31;
  1473.         readmchar_escape();
  1474.         column = achar - 31;
  1475.         lgotoxy(column, row);
  1476.         }
  1477.         /* direct cursor address */
  1478.         break;
  1479.     case 'Z':
  1480.         if (tt_type == TT_VT102) {
  1481.         /* Device Attributes */
  1482.         /* Send  Esc[?6c */ /* (was "ESC [ ? 6 ; 2 c"  - fdc) */
  1483.         sendstr("[?6c");
  1484.         }
  1485.         /* Device Attributes */
  1486.         else
  1487.         /* VT52 control */
  1488.         sendstr("/Z");
  1489.         break;
  1490.     case 'c':
  1491.         /* Reset */
  1492.         doreset();
  1493.         break;
  1494.     case '#':
  1495.         /* Esc # sequence */
  1496.         readmchar_escape();
  1497.         switch (achar) {
  1498.         case '3':
  1499.         decdwl_escape(TRUE);
  1500.         break;
  1501.         case '4':
  1502.         decdwl_escape(TRUE);
  1503.         break;
  1504.         case '5':
  1505.         decdwl_escape(FALSE);
  1506.         break;
  1507.         case '6':
  1508.         decdwl_escape(TRUE);
  1509.         break;
  1510.         case '8':
  1511.         {
  1512.             char            cell[2];
  1513.             cell[0] = 'E';
  1514.             cell[1] = 7;
  1515.             /* Self Test */
  1516.             VioWrtNCell(cell, 1920, 0, 0, 0);
  1517.             setmargins(1, ysize);
  1518.             lgotoxy(1, 1);
  1519.         }
  1520.         break;
  1521.         /* Self Test */
  1522.         default:
  1523.         break;
  1524.         }
  1525.         break;
  1526.         /* Esc # sequence */
  1527.     case '=':
  1528.         tt_keypad = FALSE;
  1529.         break;
  1530.     case '>':
  1531.         tt_keypad = TRUE;
  1532.         break;
  1533.     case '<':
  1534.         /* VT52 control */
  1535.         tt_type = TT_VT102;
  1536.         break;
  1537.     case '(':
  1538.         readmchar_escape();
  1539.         g0 = achar;
  1540.         break;
  1541.     case ')':
  1542.         readmchar_escape();
  1543.         g1 = achar;
  1544.         break;
  1545.     default:
  1546.         if (achar == 12) {
  1547.         lgotoxy(1, 1);
  1548.         clrscreen();
  1549.         }
  1550.         break;
  1551.     }
  1552.     /* First Level Case  */
  1553.     } /* Screen escape sequences  */
  1554.  
  1555. /* Host said to turn off the printer. */
  1556.  
  1557.   if (turnoffprinter) {
  1558.       turnoffprinter = FALSE;
  1559.       if (lst && !lstclosed)
  1560.     fclose(lst);
  1561.       lstclosed = TRUE;
  1562.       printon = FALSE;
  1563.   }
  1564.  
  1565. /* If printer is on, print this escape sequence. */
  1566.  
  1567.     if (printon) {
  1568.     fprintf(lst, "%c", 27);
  1569.     if (esclast > 0) {
  1570.         /* print esc sequence */
  1571.         for (i = 1; i <= esclast; ++i)
  1572.           fprintf(lst, "%c", escbuffer[i]);
  1573.     }
  1574.     }
  1575. /*
  1576.   If we just got a "printer on" directive, turn on the printer now.
  1577.   This way, the "printer on" directive itself is not printed.
  1578. */
  1579.     if (turnonprinter) {        /* Last command was "printer on" */
  1580.     turnonprinter = FALSE;
  1581.     if (lstclosed || !lst)        /* Open printer device */
  1582.       lst = fopen("prn", "w");
  1583.     if (lst) {            /* Open OK? */
  1584.         lstclosed = FALSE;        /* So not closed */
  1585.         printon = TRUE;        /* and printer is on. */
  1586.     }
  1587.     }
  1588. }
  1589.  
  1590. /* ================================================================== */
  1591. /* VT100 emulate a DEC VT100 terminal writing a character             */
  1592. /* ================================================================== */
  1593. static void
  1594. vt100(unsigned char vtch) {
  1595.     int             i, j;
  1596.     char           *s, str[2];
  1597.     /* vt100 */
  1598.     if (screenon) {
  1599.     if (vtch < 32) {    /* Control Character */
  1600.         achar = vtch;    /* Let the rest of this module see the value */
  1601.         switch (achar) {
  1602.         case LF:
  1603.             if (linemode) wherex=1;
  1604.         wrtch((char) achar);
  1605.         break;
  1606.         case CR:
  1607.         wrtch((char) achar);
  1608.         break;
  1609.         /* ESC */
  1610.         case 27:
  1611.         vtescape();
  1612.         break;
  1613.         case 14:        /* SO */
  1614.         g0g1 = &g1;
  1615.         break;
  1616.         /* SI */
  1617.         case 15:
  1618.         g0g1 = &g0;
  1619.         break;
  1620.         /* BS */
  1621.         case 8:
  1622.         wrtch((char) achar);
  1623.         break;
  1624.         case 12:        /* FF */
  1625.         case 11:        /* VT */
  1626.         /* take as lf */
  1627.         achar = 10;
  1628.         wrtch(10);
  1629.         break;
  1630.         case 7:        /* BEL */
  1631.         bleep();
  1632.         break;
  1633.         case 5:        /* ENQ */
  1634.         if (tt_answer) {
  1635.             s = answerback;
  1636.             while (*s)
  1637.               sendchar(*s++);
  1638.         }
  1639.         break;
  1640.         case 9:        /* tab character */
  1641.         j = dwl[wherey - 1] ? 2 : 1;
  1642.         i = wherex;
  1643.         if (j == 2 && htab[(i - 1) / j + 1] == 'T') {
  1644.             i++;
  1645.             cursorright();
  1646.         }
  1647.         if (i < xsize)
  1648.             do {
  1649.             i++;
  1650.             cursorright();
  1651.             } while ((htab[(i - 1) / j + 1] != 'T') &&
  1652.                  (i <= xsize - j));
  1653.         break;
  1654.         default:        /* ignore it */
  1655.         break;
  1656.         }
  1657.         /* end of Control Character */
  1658.     } else {
  1659.         if (vtch != DEL) {    /* Normal char */
  1660.         if (tt_type == TT_VT102) {
  1661.             if (*g0g1 == 'A') {    /* UK ascii set */
  1662.             /* if (vtch == 35)
  1663.                 vtch = 156; */
  1664.             } else if ((*g0g1 == '0') &&
  1665.                    (95 <= vtch) && (vtch <= 126)) {
  1666.             literal = TRUE;
  1667.             vtch = graphicset[vtch - 95];
  1668.             }
  1669.         } else {
  1670.             if (vt52graphics && (95 <= vtch) && (vtch <= 126)) {
  1671.             literal = TRUE;
  1672.             vtch = graphicset[vtch - 95];
  1673.             }
  1674.         }
  1675.         if (wherex != (dwl[wherey - 1] ? xsize - 1 : xsize)) {
  1676.             wrtch(vtch);
  1677.             if (dwl[wherey - 1])
  1678.             wrtch(' ');
  1679.             wrapit = FALSE;
  1680.         } else {
  1681.             if (wrapit) {    /* Next line  */
  1682.             if (marginbot <= wherey) {    /* Scroll up */
  1683.                 scroll(UPWARD, margintop - 1, marginbot - 1, 1);
  1684.                 lgotoxy(1, wherey);
  1685.             } else
  1686.                 lgotoxy(1, wherey + 1);
  1687.             wrtch(vtch);
  1688.             if (dwl[wherey - 1])
  1689.                 wrtch(' ');
  1690.             wrapit = FALSE;
  1691.             } else {    /* put char on last column */
  1692.             i = dwl[wherey - 1] ? 2 : 1;
  1693.             str[0] = vtch;
  1694.             str[1] = ' ';
  1695.             VioWrtCharStrAtt(&vtch, i,
  1696.                      wherey - 1,
  1697.                      xsize - i,
  1698.                      &attribute,
  1699.                      0);
  1700.             literal = FALSE;
  1701.             if ((tt_wrap && !deccolm))
  1702.                 wrapit = TRUE;
  1703.             }
  1704.         }
  1705.         }            /* Normal char */
  1706.     }
  1707.     }
  1708.     if (printon && (vtch != 27))
  1709.       fprintf(lst, "%c", vtch);
  1710. }
  1711.  
  1712. /* save current status of screen */
  1713. savescreen(ascreen *scrn) {
  1714.     USHORT n = xsize * (ysize + 1) * 2;
  1715.     scrn->ox = wherex;
  1716.     scrn->oy = wherey;
  1717.     scrn->att = attribute;
  1718.     VioReadCellStr((char *) (scrn->scrncpy), &n, 0, 0, 0);
  1719. }
  1720.  
  1721. /* restore state of screen */
  1722. restorescreen(ascreen *scrn) {
  1723.     movetoscreen(scrn->scrncpy, 1, 1, xsize * (ysize + 1) * 2);
  1724.     attribute = scrn->att;
  1725.     wherey = scrn->oy;
  1726.     wherex = scrn->ox;
  1727.     lgotoxy(wherex, wherey);
  1728. }
  1729.  
  1730. #ifdef M_I286
  1731. /* Avoid 16-bit stack overflows */
  1732. #define logchar(c) zchout(ZSFILE,c)
  1733. #else
  1734. void
  1735. logchar(char c) {
  1736.     if (zchout(ZSFILE,c) < 0) {
  1737.     conoll("");
  1738.     conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
  1739.     seslog = 0;
  1740.     }
  1741. }
  1742. #endif /* M_I286 */
  1743.  
  1744. sendcharduplex(unsigned char key) {
  1745.     unsigned char csave;
  1746.  
  1747.     key &= cmdmsk;        /* Do any requested masking */
  1748.     csave = key;
  1749.  
  1750.     if (outesc == ES_NORMAL) { /* If not inside escape seq.. */
  1751.     /* Translate character sets */
  1752.     if (sxo) key = (*sxo)(key); /* Local to intermediate. */
  1753.     if (rxo) key = (*rxo)(key); /* Intermediate to remote. */
  1754.     }
  1755.     if (oskipesc) outesc = chkaes(outesc, key);
  1756.     /* Check escape sequence status */
  1757.  
  1758.     if (sosi) {                      /* Shift-In/Out selected? */
  1759.     if (cmask == 0177) {         /* In 7-bit environment? */
  1760.         if (key & 0200) {        /* 8-bit character? */
  1761.         if (outshift == 0) { /* If not shifted, */
  1762.             sendchar(SO);    /* shift. */
  1763.             outshift = 1;
  1764.         }
  1765.         } else {
  1766.         if (outshift == 1) { /* 7-bit character */
  1767.             sendchar(SI);    /* If shifted, */
  1768.             outshift = 0;    /* unshift. */
  1769.         }
  1770.         }
  1771.     }
  1772.     if (key == SO) outshift = 1;    /* User typed SO */
  1773.     if (key == SI) outshift = 0;    /* User typed SI */
  1774.     }
  1775.  
  1776.     key &= cmask;           /* Apply Kermit-to-host mask now. */
  1777.     if (key == '\015') {           /* Handle TERMINAL NEWLINE */
  1778.     if (
  1779.         tnlm
  1780. #ifdef TNCODE               /* And for TELNET... */
  1781.         || (network && ttnproto == NP_TELNET)
  1782. #endif /* TNCODE */
  1783.       ) {
  1784.         sendchar(dopar('\015'));   /* Send the CR */
  1785.         if (duplex) {              /* If local echoing... */
  1786.        cwrite('\015');         /*   echo to screen */
  1787.            if (seslog)             /*   and if logging */
  1788.          logchar(csave);       /*   log it */
  1789.         }
  1790. #ifdef TNCODE
  1791.         if (network && !tn_nlm && ttnproto == NP_TELNET)
  1792.           key = '\0';
  1793.         else
  1794. #endif /* TNCODE */
  1795.           key = '\012';   /* Now insert a linefeed */
  1796.         csave = key;
  1797.       }
  1798.     }
  1799. #ifdef TNCODE
  1800.     /* If user types the 0xff character (TELNET IAC), it must be doubled. */
  1801.     else
  1802.       if (key == IAC && network && ttnproto == NP_TELNET)
  1803.     ttoc((char)IAC); /* and the other one just below. */
  1804. #endif /* TNCODE */
  1805.  
  1806.     sendchar(key);
  1807.     if (duplex) {
  1808.     cwrite(csave);
  1809.     if (seslog) logchar(csave);
  1810.     }
  1811. }
  1812.  
  1813. sendstrduplex(unsigned char *s, int escape) {
  1814.     if (escape)
  1815.         sendcharduplex(27);
  1816.     for ( ; *s; s++ )
  1817.         sendcharduplex(*s);
  1818. }
  1819.  
  1820. void
  1821. scrollback(int key) {
  1822.   int linesleft, nextline, nlines, i, il, nolblines;
  1823.  
  1824.   savescreen(&savedscreen);
  1825.   killcursor();
  1826.  
  1827.   linesleft = paginginfo.numlines;
  1828.   nextline = paginginfo.botline;
  1829.  
  1830.   do
  1831.   {
  1832.     if ((key & 0xFF) == 71 || (key & 0xFF) == 73 || (key & 0xFF) == 132)
  1833.     {
  1834.       /* Page Up or Home */
  1835.       if (linesleft == 0)
  1836.           bleep();
  1837.       else
  1838.       {
  1839.         /* scroll up a page */
  1840.         nlines = (key & 0xFF) == 73 ? ysize
  1841.                : (key & 0xFF) == 71 ? linesleft : 1;
  1842.  
  1843.         if (nlines > linesleft)
  1844.           nlines = linesleft;
  1845.  
  1846.         if (nlines >= ysize)
  1847.         {
  1848.           if (nlines > ysize)
  1849.             nextline = paginginfo.topline + ysize - 1;
  1850.  
  1851.           for (il = ysize; il >= 1; il--)
  1852.           {
  1853.             movetoscreen(paginginfo.buffer + xsize * 2 * nextline, 1,
  1854.                          il, xsize * 2);
  1855.  
  1856.             if (nextline == 0)
  1857.               nextline = LBUFSIZE - 1;
  1858.             else
  1859.               nextline--;
  1860.           }
  1861.         }
  1862.         else
  1863.         {
  1864.           scroll(DOWNWARD, 0, ysize - 1, nlines);
  1865.  
  1866.           for (il = 1; il <= nlines; il++)
  1867.           {
  1868.             movetoscreen(paginginfo.buffer + xsize * 2 * nextline, 1,
  1869.                          nlines - il + 1, xsize * 2);
  1870.  
  1871.             if (nextline == 0)
  1872.               nextline = LBUFSIZE - 1;
  1873.             else
  1874.               nextline--;
  1875.           }
  1876.         }
  1877.  
  1878.         linesleft = linesleft - nlines;
  1879.       }
  1880.     }
  1881.     else if ((key & 0xFF) == 81 || (key & 0xFF) == 118)
  1882.     {
  1883.       nlines = (key & 0xFF) == 81 ? ysize : 1;    /* Page Down */
  1884.  
  1885.       if (nlines > paginginfo.numlines - linesleft)
  1886.         nlines = paginginfo.numlines - linesleft;
  1887.  
  1888.       if (nlines < ysize)
  1889.         scroll(UPWARD, 0, ysize - 1, nlines);
  1890.  
  1891.       do
  1892.       {
  1893.         if (++nextline >= LBUFSIZE)
  1894.           nextline = 0;
  1895.  
  1896.         linesleft++;
  1897.         /* lines of ext display above top of the screen */
  1898.         nolblines = paginginfo.numlines - linesleft;
  1899.         /* no. of ext disp buffer lines on screen */
  1900.  
  1901.         if (nolblines >= ysize)
  1902.         {
  1903.           i = nextline + ysize;
  1904.           if (i >= LBUFSIZE)
  1905.             i -= LBUFSIZE;
  1906.  
  1907.           /* move from buffer */
  1908.           movetoscreen(paginginfo.buffer + xsize * 2 * i, 1,
  1909.                        ysize - nlines + 1, xsize * 2);
  1910.         }
  1911.         else
  1912.         {
  1913.           /* move from the screen copy */
  1914.           movetoscreen(&(savedscreen.scrncpy
  1915.                          [(ysize - 1 - nolblines) * xsize * 2]), 1,
  1916.                        ysize - nlines + 1, xsize * 2);
  1917.         }
  1918.  
  1919.         nlines--;
  1920.       }
  1921.       while (nlines > 0);
  1922.     }
  1923.     else
  1924.       linesleft = paginginfo.numlines;
  1925.  
  1926.     if (linesleft != paginginfo.numlines)
  1927.     {
  1928.       sprintf(usertext, " Scroll: %d/%d",
  1929.               paginginfo.numlines - linesleft, paginginfo.numlines);
  1930.       strcpy(helptext, "[^]PageUp/Dn");
  1931.       strcpy(exittext, "Home/End");
  1932.       line25();
  1933.  
  1934.       if ( (key = keymap[congks(0)]) < 0x100 )
  1935.         key = 32;
  1936.     }
  1937.   }
  1938.   while (linesleft != paginginfo.numlines);
  1939.  
  1940.   restorescreen(&savedscreen);
  1941.   newcursor();
  1942.   ipadl25();
  1943. }
  1944.  
  1945. void
  1946. vt100key(int key) {
  1947.     void doesc(int);
  1948.     int helpconnect(int);
  1949.     char str[3];
  1950.     int prt, st;
  1951.  
  1952.     if ( macrotab[key] ) {
  1953.       sendstrduplex(macrotab[key], 0);
  1954.       return;
  1955.     }
  1956.  
  1957.     key = keymap[key];
  1958.  
  1959.     if (key < 0x100) {
  1960.     sendcharduplex((char) key);
  1961.     if (key == CR && linemode)
  1962.         sendcharduplex(LF);
  1963.         return;
  1964.     }
  1965.  
  1966.     switch (key & 0xFF) {
  1967.     case 72:
  1968.         /* up */
  1969.         if (tt_type == TT_VT102) {
  1970.             if (tt_arrow)
  1971.                 sendstrduplex("OA", 1);
  1972.             else
  1973.                 sendstrduplex("[A", 1);
  1974.         } else
  1975.             sendstrduplex("A", 1);
  1976.         break;
  1977.     case 75:
  1978.         /* left */
  1979.         if (tt_type == TT_VT102) {
  1980.             if (tt_arrow)
  1981.                 sendstrduplex("OD", 1);
  1982.             else
  1983.                 sendstrduplex("[D", 1);
  1984.         } else
  1985.             sendstrduplex("D", 1);
  1986.         break;
  1987.     case 77:
  1988.         /* right */
  1989.         if (tt_type == TT_VT102) {
  1990.             if (tt_arrow)
  1991.                 sendstrduplex("OC", 1);
  1992.             else
  1993.                 sendstrduplex("[C", 1);
  1994.         } else
  1995.             sendstrduplex("C", 1);
  1996.         break;
  1997.     case 80:
  1998.         /* down */
  1999.         if (tt_type == TT_VT102) {
  2000.             if (tt_arrow)
  2001.                 sendstrduplex("OB", 1);
  2002.             else
  2003.                 sendstrduplex("[B", 1);
  2004.         } else
  2005.             sendstrduplex("B", 1);
  2006.         break;
  2007.     case 15:                /* Backtab */
  2008.         /* backspace */
  2009.         sendcharduplex(8);
  2010.         break;
  2011.     case 83:                /* DEL */
  2012.         /* delete */
  2013.         sendcharduplex(127);
  2014.         break;
  2015.     case 59:                /* F1 */
  2016.         /* PF1 */
  2017.         if (tt_type == TT_VT102)
  2018.             sendstrduplex("OP", 1);
  2019.         else
  2020.             sendstrduplex("P", 1);
  2021.         break;
  2022.     case 60:                /* F2 */
  2023.         /* PF2 */
  2024.         if (tt_type == TT_VT102)
  2025.             sendstrduplex("OQ", 1);
  2026.         else
  2027.             sendstrduplex("Q", 1);
  2028.         break;
  2029.     case 61:
  2030.         /* PF3 */           /* F3 */
  2031.         if (tt_type == TT_VT102)
  2032.             sendstrduplex("OR", 1);
  2033.         else
  2034.             sendstrduplex("R", 1);
  2035.         break;
  2036.     case 62:                /* F4 */
  2037.         /* PF4 */
  2038.         if (tt_type == TT_VT102)
  2039.             sendstrduplex("OS", 1);
  2040.         else
  2041.             sendstrduplex("S", 1);
  2042.         break;
  2043.     case 120:               /* Alt-1 ... Alt-9 */
  2044.     case 121:
  2045.     case 122:
  2046.     case 123:
  2047.     case 124:
  2048.     case 125:
  2049.     case 126:
  2050.     case 127:
  2051.     case 128:
  2052.     case 129:           /* This one is Alt-0 */
  2053.         /* numeric 1-9,0 */
  2054.     if (tt_keypad) {        /* Keypad digits in numeric mode*/
  2055.         if (key == 129) key = 48;    /* Watch out for zero */
  2056.         else key -= 71;
  2057.         sendcharduplex((unsigned char)key);    /* send digit */
  2058.         } else {
  2059.             key = 'q' + (key & 0xFF) - 120;
  2060.             if (key == 'z')
  2061.                 key = 'p';
  2062.             /* alt 0 */
  2063.             if (tt_type == TT_VT102)
  2064.                 strcpy(str, "O ");
  2065.             else
  2066.                 strcpy(str, "? ");
  2067.             str[1] = key;
  2068.             sendstrduplex(str, 1);
  2069.         }
  2070.         break;
  2071.     case 63:                /* Keypad minus = F5 or ... */
  2072.     case 64:                /* F6 */
  2073.     if (tt_keypad)            /* Keypad in numeric mode */
  2074.         sendcharduplex('-');
  2075.         else if (tt_type == TT_VT102)    /* Application mode, VT102 */
  2076.             sendstrduplex("Om", 1);
  2077.         else                /* Application mode, VT52 */
  2078.             sendstrduplex("?m", 1);
  2079.         break;
  2080.     case 65:                /* Keypad comma = F7 or ... */
  2081.     case 66:                /* F8 */
  2082.     if (tt_keypad)
  2083.         sendcharduplex(',');
  2084.         else if (tt_type == TT_VT102)
  2085.             sendstrduplex("Ol", 1);
  2086.         else
  2087.             sendstrduplex("?l", 1);
  2088.         break;
  2089.     case 67:                /* Keypad period = F9 */
  2090.     if (tt_keypad)
  2091.         sendcharduplex('.');
  2092.         else if (tt_type == TT_VT102)
  2093.             sendstrduplex("On", 1);
  2094.         else
  2095.             sendstrduplex("?n", 1);
  2096.         break;
  2097.     case 68:                /* Keypad Enter = F10 */
  2098.     if (tt_keypad) {
  2099.         sendcharduplex('\015');    /* Numeric mode, send CR */
  2100.         if (tnlm)
  2101.           sendcharduplex('\012');    /* Newline mode, send LF too */
  2102.         } else if (tt_type == TT_VT102)
  2103.       sendstrduplex("OM", 1);
  2104.         else
  2105.       sendstrduplex("?M", 1);
  2106.         break;
  2107.     case 255:                /* Scroll-Lock */
  2108.         {
  2109.             strcpy(usertext, " Scroll-Lock ");
  2110.             *exittext = '\0';
  2111.             *helptext = '\0';
  2112.             line25();
  2113.             while (keymap[congks(0)] != 0x1FF) ;
  2114.             ipadl25();
  2115.         }
  2116.         break;
  2117.     case 81:                /* Page-Down */
  2118.     case 118:               /* Control-Page-Down */
  2119.         bleep();
  2120.         /* since not in extended display mode */
  2121.         break;
  2122.     case 71:                /* Home           enter extended display mode */
  2123.     case 73:                /* Page-Up  */
  2124.     case 132:               /* Control-Page-Up */
  2125.         if (paginginfo.numlines == 0)
  2126.             bleep();
  2127.             else
  2128.             scrollback(key);
  2129.         break;
  2130.     case 16:                /* Alt-Q = Quit */
  2131.       doesc('Q'); break;
  2132.     case 45:                /* Alt-X = Return to prompt */
  2133.       doesc('C'); break;
  2134.     case 48:                /* Alt-B = Send BREAK */
  2135.       doesc('B'); break;
  2136.     case 38:                /* Alt-L = Send Long BREAK */
  2137.       doesc('L'); break;
  2138.     case 35:                /* Alt-H = Hangup */
  2139.       doesc('H'); break;
  2140.     case 131:                /* Alt-= is Reset */
  2141.       doreset();
  2142. #ifdef COMMENT
  2143.       clearscreen(0, attribute);
  2144.       savescreen(&vt100screen);
  2145. #endif /* COMMENT */
  2146.       break;
  2147.     case 53:                /* Alt-? or Alt-/ = Help */
  2148.       strcpy(usertext, " Press any key to restore the screen");
  2149.       exittext[0] = '\0';
  2150.       helptext[0] = '\0';
  2151.       line25();
  2152.       helpconnect(1);
  2153.       ipadl25();
  2154.       break;
  2155.     default:                /* Others, ignore */
  2156.         break;
  2157.     }
  2158.     /* of case */
  2159. }
  2160.  
  2161. /* ------------------------------------------------------------------ */
  2162. /* cwrite                                                             */
  2163. /* ------------------------------------------------------------------ */
  2164. cwrite(unsigned char ch)
  2165. {
  2166.     {
  2167.     /* check and process escape sequence */
  2168.     /* escape */
  2169.     if (ch == 27) {
  2170.         escaping = TRUE;
  2171.         esclast = 0;
  2172.     } else {
  2173.         if (!(escaping)) {
  2174.         /* can send it to vt100 to be processed */
  2175.         vt100(ch);
  2176.         } else {
  2177.         /* in the middle of an escape sequence */
  2178.         if (((ch == 24) || (ch == 26)))
  2179.             /* cancelled */
  2180.             escaping = FALSE;
  2181.         else {
  2182.             if (ch < 32) {
  2183.             if (ch == 8) {    /* Backspace */
  2184.                 if (esclast >= 1)
  2185.                 esclast--;
  2186.             }
  2187.             } else {
  2188.             /* add to control string */
  2189.             if (esclast < 128) {
  2190.                 /* add to buffer */
  2191.                 esclast = esclast + 1;
  2192.                 escbuffer[esclast] = ch;
  2193.             }
  2194.             /* now check to see if sequence complete */
  2195.             {
  2196.                 if (tt_type == TT_VT102) {
  2197.                 if (escbuffer[1] != '[') {
  2198.                     char            c = escbuffer[1];
  2199.                     if ((c != '#' &&
  2200.                      c != '(' &&
  2201.                      c != ')' &&
  2202.                      c != 'O' &&
  2203.                      c != '?') ||
  2204.                     esclast >= 2) {
  2205.                     if ((escbuffer[1] != 'Y'))
  2206.                         vtescape();
  2207.                     else {
  2208.                         if ((esclast == 3))
  2209.                         vtescape();
  2210.                     }
  2211.                     }
  2212.                 } else {
  2213.                     /* check for terminating character */
  2214.                     if ((((64 <= ch) &&
  2215.                       (ch <= 126)) &&
  2216.                      (esclast > 1)))
  2217.                     vtescape();
  2218.                 }
  2219.                 } else {
  2220.                 /* vt52 mode */
  2221.                 if ((escbuffer[1] != 'Y'))
  2222.                     vtescape();
  2223.                 else {
  2224.                     if (esclast == 3)
  2225.                     vtescape();
  2226.                 }
  2227.                 }
  2228.             }
  2229.             }
  2230.         }
  2231.         }
  2232.     }
  2233.     }
  2234. }
  2235.  
  2236. /*---------------------------------------------------------------------------*/
  2237. /* scrninit                                                                  */
  2238. /*---------------------------------------------------------------------------*/
  2239. scrninit() {
  2240.     if ( paginginfo.bufsize != tt_scrsize ) {
  2241.         if ( paginginfo.buffer != NULL )
  2242.         free(paginginfo.buffer);
  2243.     paginginfo.buffer = NULL;
  2244.     scrninitialised = 0;
  2245.     }
  2246.     if (!scrninitialised) {
  2247.     scrninitialised = 1;
  2248.     defaultattribute = colornormal;
  2249.     attribute = defaultattribute;
  2250.     /* Initialise paging info */
  2251.         if ( paginginfo.buffer == NULL ) {
  2252.       paginginfo.bufsize = tt_scrsize;
  2253.       paginginfo.buffer = malloc(tt_scrsize * xsize * 2);
  2254.     }
  2255.     assert(paginginfo.buffer != NULL);
  2256.     paginginfo.numlines = 0;
  2257.     paginginfo.topline = 0;
  2258.     paginginfo.botline = LBUFSIZE - 1;
  2259.     clearscreen(0, attribute);
  2260.     savescreen(&vt100screen);
  2261.     }
  2262. }
  2263.  
  2264. /*---------------------------------------------------------------------------*/
  2265. /* bleep                                                                     */
  2266. /*---------------------------------------------------------------------------*/
  2267. bleep() {
  2268.     DosBeep(880, 50);
  2269. }
  2270.  
  2271. /*---------------------------------------------------------------------------*/
  2272. /* wrtch                                                                     */
  2273. /*---------------------------------------------------------------------------*/
  2274. wrtch(char ch) {
  2275.     char cell[2];
  2276.     if (ch >= ' ' || literal) {    /* Normal character */
  2277.     if ((tt_type == TT_VT102) && insertmode) {
  2278.         cell[0] = ch;
  2279.         cell[1] = attribute;
  2280.         VioScrollRt(wherey - 1, wherex - 1, wherey - 1,
  2281.             xsize - 1, 1, cell, 0);
  2282.     } else
  2283.         VioWrtCharStrAtt(&ch, 1, wherey - 1, wherex - 1, &attribute, 0);
  2284.     literal = FALSE;
  2285.     if (++wherex > xsize) {
  2286.         wherex = 1;
  2287.         wrtch(LF);
  2288.     }
  2289.     } else {            /* Control character */
  2290.     switch (ch) {
  2291.     case LF:
  2292.         if (wherey == marginbot) {
  2293.         if (margintop == 1)
  2294.             toplinetocyclicbuffer();
  2295.         scroll(UPWARD, margintop - 1, marginbot - 1, 1);
  2296.         } else {
  2297.         wherey++;
  2298.         if (wherey == ysize + 1)
  2299.             wherey--;
  2300.         }
  2301.         break;
  2302.     case CR:
  2303.         wherex = 1;
  2304.         break;
  2305.     case BS:
  2306.         if (wherex > 1)
  2307.         wherex--;
  2308.         break;
  2309.     case 12:
  2310.         if (wherex < xsize)
  2311.         wherex++;
  2312.         break;
  2313.     case BEL:
  2314.         DosBeep(440, 100);
  2315.         break;
  2316.     default:{        /* Ignore */
  2317.         }
  2318.     }
  2319.     }
  2320.     if (cursoron)
  2321.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  2322. }
  2323.  
  2324. /*---------------------------------------------------------------------------*/
  2325. /* clearscreen                                                               */
  2326. /*---------------------------------------------------------------------------*/
  2327. clearscreen(int all, int attr) {
  2328.     char cell[2];
  2329.     cell[0] = ' ';
  2330.     cell[1] = attr;
  2331.     VioWrtNCell(cell, xsize * ysize + (all ? xsize : 0), 0, 0, 0);
  2332.     lgotoxy(1, 1);
  2333. }
  2334.  
  2335. /*---------------------------------------------------------------------------*/
  2336. /* lgotoxy                                                                   */
  2337. /*---------------------------------------------------------------------------*/
  2338. lgotoxy(int x, int y) {
  2339.     wherex = x;
  2340.     wherey = y;
  2341.     if (cursoron)
  2342.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  2343. }
  2344.  
  2345. /*---------------------------------------------------------------------------*/
  2346. /* scroll                                                                    */
  2347. /*---------------------------------------------------------------------------*/
  2348. scroll(int updown, int top, int bottom, int nlines) {
  2349.     char blankcell[2];
  2350.     int i;
  2351.  
  2352.     blankcell[0] = ' ';
  2353.     blankcell[1] = attribute;
  2354.     switch (updown) {
  2355.     case UPWARD:
  2356.     VioScrollUp(top, 0, bottom, xsize - 1, nlines, blankcell, 0);
  2357.         VioShowBuf(0, xsize * 2, 0);
  2358.         /* There is a bug in early OS/2 2.0 8514/A PM drivers that causes
  2359.          * wrong screen update after a scroll operation. We just force
  2360.          * a correct screen update of the line in question here. */
  2361.     if (dwls) {
  2362.         for (i = top; i <= bottom - nlines; i++)
  2363.         dwl[i] = dwl[i + nlines];
  2364.         for (i = bottom - nlines + 1; i <= bottom; i++)
  2365.             dwl[i] = FALSE;
  2366.     }
  2367.     break;
  2368.     case DOWNWARD:
  2369.     VioScrollDn(top, 0, bottom, xsize - 1, nlines, blankcell, 0);
  2370.         VioShowBuf(xsize * 2, xsize * 2, 0);
  2371.     if (dwls) {
  2372.         for (i = bottom; i >= top + nlines; i--)
  2373.         dwl[i] = dwl[i - nlines];
  2374.         for (i = top + nlines - 1; i >= top; i--)
  2375.             dwl[i] = FALSE;
  2376.     }
  2377.     break;
  2378.     default: /* ignore */ ;
  2379.     }
  2380.     if (dwls) {
  2381.     dwls = FALSE;
  2382.     for (i = 0; i < ysize; i++)
  2383.         if (dwl[i]) {
  2384.         dwls = TRUE;
  2385.         break;
  2386.         }
  2387.     }
  2388. }
  2389.  
  2390. /*---------------------------------------------------------------------------*/
  2391. /* movetoscreen                                                              */
  2392. /*---------------------------------------------------------------------------*/
  2393. movetoscreen(char *source, int x, int y, int len) {
  2394.     VioWrtCellStr(source, len, y - 1, x - 1, 0);
  2395. }
  2396.  
  2397. /*---------------------------------------------------------------------------*/
  2398. /* toplinetocyclicbuffer                                                     */
  2399. /*---------------------------------------------------------------------------*/
  2400. toplinetocyclicbuffer() {
  2401.     USHORT n = xsize * 2;
  2402.     if (paginginfo.numlines == LBUFSIZE) {
  2403.     if (++paginginfo.topline == LBUFSIZE)
  2404.         paginginfo.topline = 0;
  2405.     } else
  2406.     paginginfo.numlines++;
  2407.     if (++paginginfo.botline == LBUFSIZE)
  2408.     paginginfo.botline = 0;
  2409.     VioReadCellStr((paginginfo.buffer + xsize * 2 * paginginfo.botline),
  2410.            &n, 0, 0, 0);
  2411. }
  2412.  
  2413. /*---------------------------------------------------------------------------*/
  2414. /* cleartoeol                                                                */
  2415. /*---------------------------------------------------------------------------*/
  2416. clrtoeoln() {
  2417.     char            cell[2];
  2418.  
  2419.     cell[0] = ' ';
  2420.     cell[1] = attribute;
  2421.     VioWrtNCell(cell, xsize + 1 - wherex, wherey - 1, wherex - 1, 0);
  2422. }
  2423.  
  2424. /*---------------------------------------------------------------------------*/
  2425. /* setmargins                                                                */
  2426. /*---------------------------------------------------------------------------*/
  2427. setmargins(int top, int bot) {
  2428.     margintop = top;
  2429.     marginbot = bot;
  2430. }
  2431.  
  2432. /*---------------------------------------------------------------------------*/
  2433. /* killcursor                                                                */
  2434. /*---------------------------------------------------------------------------*/
  2435. killcursor() {
  2436.     VIOCURSORINFO   nocursor;
  2437.     if (!cursoron)
  2438.     return 0;
  2439.     VioGetCurType(&crsr_info, 0);    /* Store current cursor type */
  2440.     nocursor = crsr_info;    /* MS C allows this */
  2441.     nocursor.attr = -1;
  2442.     VioSetCurType(&nocursor, 0);/* Hide cursor */
  2443. }
  2444.  
  2445. /*---------------------------------------------------------------------------*/
  2446. /* newcursor                                                                 */
  2447. /*---------------------------------------------------------------------------*/
  2448. newcursor() {
  2449.     VioSetCurType(&crsr_info, 0);
  2450.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  2451.     cursoron = TRUE;
  2452. }
  2453.  
  2454. /*---------------------------------------------------------------------------*/
  2455. /* line25                                                                    */
  2456. /*---------------------------------------------------------------------------*/
  2457.  
  2458. strinsert(char *d, char *s) {
  2459.     while (*s)
  2460.     *d++ = *s++;
  2461. }
  2462.  
  2463. line25() {
  2464.     char s[132];
  2465.     int  i;
  2466.     char attr;
  2467.  
  2468.     for (i = 0; i < xsize; i++)
  2469.     s[i] = ' ';
  2470.     strinsert(&s[00], usertext);
  2471.     strinsert(&s[20], helptext);
  2472.     strinsert(&s[33], exittext);
  2473.     strinsert(&s[52], hostname);
  2474.     strinsert(&s[65], filetext);
  2475.     attr = colorstatus;
  2476.     VioWrtCharStrAtt(s, xsize, ysize, 0, &attr, 0);
  2477. }
  2478.  
  2479. sendstr(char * s) {
  2480.     sendchar(27);
  2481.     while (*s)
  2482.     sendchar(*s++);
  2483. }
  2484.  
  2485. /*
  2486.  * RDSERWRTSCR  --  Read the comms line and write to the screen.
  2487.  * This function is executed by a separate thread.
  2488.  */
  2489.  
  2490. int
  2491. ckcgetc(int dummy) {
  2492.     return ttinc(1);
  2493. }
  2494.  
  2495. #ifdef __32BIT__
  2496. long FAR
  2497. rdserwrtscr(long param)
  2498. #else
  2499. void FAR
  2500. rdserwrtscr()
  2501. #endif
  2502. {
  2503.     int c, tx;
  2504.  
  2505.     DosSetPrty(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
  2506. #ifdef __32BIT__
  2507.     DosPostEventSem(threadsem);
  2508. #else
  2509.     DosSemClear(&threadsem);    /* Let him know we've started */
  2510. #endif
  2511.  
  2512.     while (active) {
  2513.         c = ttinc(-50);
  2514.     if (!active)
  2515.         break;
  2516.     if (c >= 0) {
  2517.  
  2518. #ifdef TNCODE
  2519.           /* Handle TELNET negotiations here */    
  2520.         if (c == IAC && network && ttnproto == NP_TELNET) {
  2521.           if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) {
  2522.         continue;
  2523.           } else if (tx == -1) { /* I/O error */
  2524.             strcpy(termessage, "Connection closed.\n");
  2525.         active = FALSE;
  2526.         break;
  2527.           } else if ((tx == 1) && (!duplex)) { /* ECHO change */
  2528.         duplex = 1;
  2529.           } else if ((tx == 2) && (duplex)) { /* ECHO change */
  2530.         duplex = 0;
  2531.           } else if (tx == 3) { /* Quoted IAC */
  2532.         c = 255;
  2533.           } else continue;    /* Negotiation OK, get next char. */
  2534.         }
  2535. #endif /* TNCODE */
  2536.  
  2537.         DosEnterCritSec();
  2538.  
  2539.         if (cursoron)
  2540.         if (ttchk() > 20) {
  2541.             killcursor();
  2542.             cursoron = FALSE;
  2543.         }
  2544.  
  2545.             c &= cmask;
  2546.  
  2547.         if (sosi) {        /* Handle SI/SO */
  2548.         if (c == SO) {    /* Shift Out */
  2549.             inshift = 1;
  2550.             goto cont;
  2551.         } else if (c == SI) { /* Shift In */
  2552.             inshift = 0;
  2553.             goto cont;
  2554.         }
  2555.         if (inshift) c |= 0200;
  2556.         }
  2557.  
  2558.         /* Translate character sets */
  2559.         if (inesc == ES_NORMAL) {
  2560.           /* Translate character sets */
  2561.           if (sxi) c = (*sxi)((CHAR)c);
  2562.           if (rxi) c = (*rxi)((CHAR)c);
  2563.         }
  2564.         if (iskipesc) inesc = chkaes(inesc, (CHAR)c);
  2565.         /* Adjust escape sequence status */
  2566.  
  2567.         c &= cmdmsk;    /* Apply command mask. */
  2568.         if (c == CR && tt_crd) { /* SET TERM CR-DISPLAY CRLF ? */
  2569.         cwrite((char) c);    /* Yes, output CR */
  2570.         if (seslog) logchar((char) c);
  2571.         c = LF;             /* and insert a linefeed */
  2572.         }
  2573.         cwrite((char) c);
  2574.         if (seslog) logchar((char) c);
  2575.  
  2576. cont:        DosExitCritSec();
  2577.     } else if (c == -2) {
  2578.             active = FALSE;
  2579.         strcpy(termessage, "Connection closed.\n");
  2580.             /* link broken */
  2581.     } else if (!cursoron) {
  2582.         DosEnterCritSec();
  2583.         newcursor();
  2584.         DosExitCritSec();
  2585.     }
  2586.     }
  2587.  
  2588. #ifndef __32BIT__
  2589.     DosEnterCritSec();        /* Stop thread 1 discarding our stack before
  2590.                  * we've gone */
  2591.     DosSemClear(&threadsem);    /* Tell him we're going to die */
  2592. #endif
  2593.     DosExit(EXIT_THREAD, 0);
  2594. }
  2595.  
  2596. /* HELPCONNECT  --  Give help message for connect.  */
  2597.  
  2598. static int helpcol, helprow;
  2599. static int helpwidth;
  2600.  
  2601. void helpstart(int w, int h)
  2602. {
  2603.     unsigned char   cell[2];
  2604.  
  2605.     cell[1] = colorhelp;
  2606.     helpwidth = w;
  2607.     helpcol = (xsize - w) / 2;
  2608.     helprow = (ysize - h) / 2 - 1;
  2609.     cell[0] = 201;        /* Top left corner */
  2610.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  2611.     cell[0] = 205;        /* Horizontal */
  2612.     VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
  2613.     cell[0] = 187;        /* Top right corner */
  2614.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  2615. }
  2616.  
  2617. void
  2618. helpline(char *s) {
  2619.     unsigned char   cell[2];
  2620.     int             i;
  2621.  
  2622.     i = strlen(s);
  2623.     helprow++;
  2624.     cell[1] = colorhelp;
  2625.     cell[0] = 186;        /* Vertical */
  2626.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  2627.     VioWrtCharStrAtt(s, i, helprow, helpcol + 1, &cell[1], 0);
  2628.     cell[0] = ' ';
  2629.     VioWrtNCell(cell, helpwidth - i, helprow, helpcol + 1 + i, 0);
  2630.     cell[0] = 186;        /* Vertical */
  2631.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  2632. }
  2633.  
  2634. void
  2635. helpend() {
  2636.     unsigned char   cell[2];
  2637.  
  2638.     helprow++;
  2639.     cell[1] = colorhelp;
  2640.     cell[0] = 200;        /* Bottom left corner */
  2641.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  2642.     cell[0] = 205;        /* Horizontal */
  2643.     VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
  2644.     cell[0] = 188;        /* Bottom right corner */
  2645.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  2646. }
  2647.  
  2648. int
  2649. helpconnect(int x) {
  2650.     int c, n;
  2651.     char line[80];
  2652.     static char    *hlpmsg[] = {
  2653.   "",
  2654.   " Command:   (SPACE to cancel)",
  2655.   "",
  2656.   "    C    to return to the C-Kermit prompt",
  2657.   "    H    to hangup and return to the prompt",
  2658.   "    Q    to hangup and quit C-Kermit",
  2659.   "    !    to enter an OS/2 command processor",
  2660.   "",
  2661.   "    0    (zero) to send a null",
  2662.   "   ^%c    to send the escape character",
  2663.   "    B    to send a BREAK",
  2664.   "    L    to send a LONG BREAK",
  2665.   "",
  2666. #ifdef TNCODE
  2667.   "    I    to interrupt process (TELNET)",
  2668.   "    A    to send 'are you there' (TELNET)",
  2669.   "",
  2670. #endif /* TNCODE */
  2671.   "    \\    backslash escape (end with ENTER):",
  2672.   "         \\nnn   decimal code",
  2673.   "         \\Onnn  octal code",
  2674.   "         \\Xhh   hexadecimal code",
  2675.   ""};
  2676. #define HELPSIZE (sizeof(hlpmsg)/sizeof(char *))
  2677.  
  2678.     static char *altmsg[] = {
  2679.   "",
  2680.   " Alt-X to return to the C-Kermit prompt",
  2681.   " Alt-H to hangup and return to the prompt",
  2682.   " Alt-Q to hangup and quit Kermit",
  2683.   " Alt-B to send a BREAK",
  2684.   " Alt-L to send a Long BREAK",
  2685.   " Alt-= to reset terminal emulator",
  2686.   "",
  2687.   " or the CONNECT-mode escape character Ctrl-%c",
  2688.   " followed by ? for additional commands",
  2689.   ""};
  2690. #define ALTSIZE (sizeof(altmsg)/sizeof(char *))
  2691.  
  2692.     n = x ? ALTSIZE : HELPSIZE;
  2693.  
  2694.     savescreen(&savedscreen);
  2695.     killcursor();
  2696.     helpstart(47, n);
  2697.     for (c = 0; c < n; c++)
  2698.       if (strchr(x ? altmsg[c] : hlpmsg[c], '%')) {
  2699.     sprintf(line, x ? altmsg[c] : hlpmsg[c], ctl(escape));
  2700.     helpline(line);
  2701.       }
  2702.       else
  2703.     helpline(x ? altmsg[c] : hlpmsg[c]);
  2704.     helpend();
  2705.     c = keymap[congks(0)];
  2706.     newcursor();
  2707.     restorescreen(&savedscreen);
  2708.     return (c);
  2709. }
  2710.  
  2711. /* CHSTR  --  Make a printable string out of a character  */
  2712.  
  2713. char*
  2714. chstr(int c) {
  2715.     static char     s[8];
  2716.     char           *cp = s;
  2717.  
  2718.     if (c < SP) {
  2719.     sprintf(cp, "CTRL-%c", ctl(c));
  2720.     } else
  2721.     sprintf(cp, "'%c'\n", c);
  2722.     cp = s;
  2723.     return (cp);
  2724. }
  2725.  
  2726. /* DOESC  --  Process an escape character argument  */
  2727.  
  2728. void
  2729. esc25(int h) {
  2730.     strcpy(usertext, " Command:");
  2731.     strcpy(exittext, h ? "" : "Return: c");
  2732.     strcpy(helptext, h ? "" : "Help: ?");
  2733.     line25();
  2734. }
  2735.  
  2736. void
  2737. doesc(int c) {
  2738.     CHAR d, temp[8];
  2739.     VIOMODEINFO mi;
  2740.  
  2741.     while (1) {
  2742.     if (c == escape) {    /* Send escape character */
  2743.         sendchar((char)c);
  2744.         return;
  2745.     } else
  2746.      /* Or else look it up below. */ if (isupper(c))
  2747.         c = tolower(c);
  2748.  
  2749.     switch (c) {
  2750.  
  2751.     case 'c':        /* return to command mode */
  2752.     case '\03':
  2753.         active = 0;
  2754.         return;
  2755.  
  2756.     case 'h':        /* Hangup and return to command mode */
  2757.      /* case '\010': */         /* Too dangerous! */
  2758.         hangnow = 1;
  2759.         active = 0;
  2760.         strcpy(termessage, "Hangup.\n");
  2761.         return;
  2762.  
  2763.     case 'q':               /* Hangup and quit */
  2764.      /*    case '\021': */         /* Too dangerous! */
  2765.         active = 0;
  2766.         hangnow = 1;
  2767.         quitnow = 1;
  2768.         strcpy(termessage, "Hangup and quit.\n");
  2769.         return;
  2770.  
  2771.     case '!':
  2772.             savescreen(&savedscreen);
  2773.             mi.cb = sizeof(mi);
  2774.             VioGetMode(&mi, 0);
  2775.             concooked();
  2776.             clearscreen(1, colorcmd);
  2777.             restorecursormode();
  2778.             puts("Enter EXIT to return to C-Kermit.");
  2779.         zshcmd("");
  2780.         conraw();
  2781.             connoi();
  2782.             VioSetMode(&mi, 0);
  2783.             setcursormode();
  2784.             restorescreen(&savedscreen);
  2785.         return;
  2786.  
  2787.     case 'b':        /* Send a BREAK signal */
  2788.     case '\02':
  2789.         ttsndb();
  2790.         return;
  2791.  
  2792.     case 'l':        /* Send a LONG BREAK signal */
  2793.     case '\014':
  2794.         ttsndlb();
  2795.         return;
  2796.  
  2797.     case '0':        /* Send a null */
  2798.         c = '\0';
  2799.         sendchar((char)c);
  2800.         return;
  2801.  
  2802. #ifdef NETCONN
  2803. #ifdef TCPSOCKET
  2804.     case 'i':            /* Send Interrupt */
  2805.         if (network && ttnproto == NP_TELNET) { /* TELNET */
  2806.         temp[0] = (CHAR) IAC;    /* I Am a Command */
  2807.         temp[1] = (CHAR) IP;    /* Interrupt Process */
  2808.         temp[2] = NUL;
  2809.         ttol((CHAR *)temp,2);
  2810.         } else 
  2811.           conoc(BEL);
  2812.         return;
  2813.  
  2814.     case 'a':            /* "Are You There?" */
  2815.         if (network && ttnproto == NP_TELNET) {
  2816.         temp[0] = (CHAR) IAC;    /* I Am a Command */
  2817.         temp[1] = (CHAR) AYT;    /* Are You There? */
  2818.         temp[2] = NUL;
  2819.         ttol((CHAR *)temp,2);
  2820.         } else conoc(BEL);
  2821.         return;
  2822. #endif /* TCPSOCKET */
  2823. #endif /* NETCONN */
  2824.  
  2825.         case '\\':
  2826.             {
  2827.                 char kbuf[32];
  2828.         char *kbp = kbuf, *text = usertext + 2;
  2829.  
  2830.         *kbp++ = c;
  2831.  
  2832.                 strcpy(usertext, " \\");
  2833.                 strcpy(exittext,"Exit: ENTER");
  2834.                 helptext[0] = 0;
  2835.                 line25();
  2836.  
  2837.         while (((c = (coninc(0) & cmdmsk)) != '\r') && (c != '\n')) {
  2838.                   if ( c == '\b' ) {
  2839.                     if ( kbp > kbuf + 1 ) {
  2840.               *--kbp = 0;
  2841.                       *--text = 0;
  2842.                     }
  2843.                   } else if ( kbp - kbuf < sizeof(kbuf) - 2 ) {
  2844.             *kbp++ = c;
  2845.                     *text++ = c;
  2846.                     *text = 0;
  2847.                   }
  2848.                   line25();
  2849.                 }
  2850.  
  2851.         *kbp = 0; kbp = kbuf;
  2852.         c = xxesc(&kbp);    /* Interpret it */
  2853.  
  2854.         if (c >= 0) {
  2855.                 sendcharduplex((char)c);
  2856.             return;
  2857.         } else {        /* Invalid backslash code. */
  2858.             conoc(BEL);
  2859.             return;
  2860.         }
  2861.         }
  2862.             return;
  2863.  
  2864.     case SP:        /* Space, ignore */
  2865.         return;
  2866.  
  2867.     default:        /* Other */
  2868.         conoc(BEL);
  2869.         return;        /* Invalid esc arg, beep */
  2870.     }
  2871.     }
  2872. }
  2873.  
  2874. /* CHECKSCREENMODE  --  Make sure we are in a usable mode */
  2875. checkscreenmode() {
  2876.     VIOMODEINFO     m;
  2877.     VIOINTENSITY vi;
  2878.  
  2879.     vi.cb = sizeof(vi);
  2880.     vi.type = 2;
  2881.     vi.fs = 1;
  2882.     VioSetState(&vi, 0);
  2883.     
  2884.     m.cb = sizeof(m);
  2885.     assert(VioGetMode(&m, 0) == 0);
  2886.  
  2887.     if ( xsize != min(132, m.col) || ysize != min(60, m.row) - 1 ) {
  2888.       scrninitialised = 0;
  2889.       if ( paginginfo.buffer )
  2890.         free(paginginfo.buffer);
  2891.       paginginfo.buffer = NULL;
  2892.       if ( vt100screen.scrncpy )
  2893.         free(vt100screen.scrncpy);
  2894.       vt100screen.scrncpy = NULL;
  2895.       if ( commandscreen.scrncpy )
  2896.         free(commandscreen.scrncpy);
  2897.       commandscreen.scrncpy = NULL;
  2898.       if ( savedscreen.scrncpy )
  2899.         free(savedscreen.scrncpy);
  2900.       savedscreen.scrncpy = NULL;
  2901.     }
  2902.  
  2903.     xsize = min(132, m.col);
  2904.     ysize = min(60, m.row) - 1;
  2905.     marginbot = ysize;
  2906.  
  2907.     if ( !vt100screen.scrncpy )
  2908.       vt100screen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  2909.     assert(vt100screen.scrncpy != NULL);
  2910.     if ( !commandscreen.scrncpy )
  2911.       commandscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  2912.     assert(commandscreen.scrncpy != NULL);
  2913.     if ( !savedscreen.scrncpy )
  2914.       savedscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  2915.     assert(savedscreen.scrncpy != NULL);
  2916. }
  2917.  
  2918. setcursormode() {
  2919.     VIOMODEINFO vmi;
  2920.     VIOCURSORINFO vci;
  2921.     int cell, bottom, top;
  2922.  
  2923.     vmi.cb = sizeof(vmi);
  2924.     VioGetMode(&vmi, 0);
  2925.     cell   = vmi.vres / vmi.row;
  2926.  
  2927.     VioGetCurType(&vci, 0);
  2928.     crsr_command = vci;
  2929.  
  2930.     vci.cEnd   = cell - 1;
  2931.     vci.yStart = (tt_cursor == 0) ? cell - 2 :
  2932.                  cell - 1 - (cell - 2) * tt_cursor / 2;
  2933.  
  2934.     VioSetCurType(&vci, 0);
  2935. }
  2936.  
  2937. restorecursormode() {
  2938.     VioSetCurType(&crsr_command, 0);
  2939. }
  2940.  
  2941. /* CONECT  --  Perform terminal connection  */
  2942. int
  2943. conect() {
  2944.     USHORT          len, x, y;
  2945.     int             c, cm;    /* c is a character, but must be signed
  2946.                  * integer to pass thru -1, which is the
  2947.                  * modem disconnection signal, and is
  2948.                  * different from the character 0377 */
  2949.     char            errmsg[50], *erp, ac, bc, ss[132];
  2950.  
  2951.     if (!network && speed < 0) {
  2952.     printf("Sorry, you must set speed first.\n");
  2953.     return (0);
  2954.     }
  2955.     twochartimes = network ? 1 : 22000L / speed;
  2956.  
  2957.     if ((escape < 0) || (escape > 0177)) {
  2958.     printf("Your escape character is not ASCII - %d\n", escape);
  2959.     return (0);
  2960.     }
  2961.     if (ttopen(ttname, &local, network ? -nettype : mdmtyp, 0) < 0) {
  2962.     erp = errmsg;
  2963.     sprintf(erp, "Sorry, can't open %s", ttname);
  2964.     perror(errmsg);
  2965.     return (0);
  2966.     }
  2967.  
  2968.     /* Condition console terminal and communication line */
  2969.     if (ttvt(speed, flow) < 0) {
  2970.     printf("Sorry, Can't condition communication line\n");
  2971.     return (0);
  2972.     }
  2973.  
  2974.     if (!network && carrier != CAR_OFF && (ttgmdm() & BM_DCD) == 0) {
  2975.         printf("No carrier detected.\n");
  2976.     return (0);
  2977.     }
  2978.  
  2979. #ifdef TNCODE
  2980.     if (network && ttnproto == NP_TELNET)
  2981.       tn_ini();
  2982. #endif /* TNCODE */
  2983.  
  2984.     outshift = inshift = 0;        /* Initial shift state. */
  2985.  
  2986.     tcs = TC_1LATIN;
  2987.     langsv = language;
  2988.     language = L_USASCII;
  2989.  
  2990.     if (tcsr == tcsl) {            /* Remote and local sets the same? */
  2991.     sxo = rxo = NULL;        /* If so, no translation. */
  2992.     sxi = rxi = NULL;
  2993.     } else {                /* Otherwise, set up */
  2994.     sxo = xls[tcs][tcsl];        /* translation function */
  2995.     rxo = xlr[tcs][tcsr];        /* pointers for output functions */
  2996.     sxi = xls[tcs][tcsr];        /* and for input functions. */
  2997.     rxi = xlr[tcs][tcsl];
  2998.     }
  2999.  
  3000.     iskipesc = oskipesc = (tcs != TC_TRANSP) &&    /* Not transparent */
  3001.       (fcsinfo[tcsl].size == 128 || fcsinfo[tcsr].size == 128) && /* 7 bits */
  3002.     (fcsinfo[tcsl].code != FC_USASCII);
  3003.     inesc = outesc = ES_NORMAL;        /* Initial state of recognizer */
  3004.  
  3005.     checkscreenmode();
  3006.     setcursormode();
  3007.     VioGetCurPos(&y, &x, 0);
  3008.     wherex = x + 1;
  3009.     wherey = y + 1;
  3010.     savescreen(&commandscreen);
  3011.     colorcmd = commandscreen.scrncpy[(x + y * xsize) * 2 + 1];
  3012.     scrninit();
  3013.     restorescreen(&vt100screen);
  3014.     conraw();
  3015.     connoi();
  3016.     ipadl25();
  3017.  
  3018.     /* Create a thread to read the comms line and write to the screen */
  3019.  
  3020.     active = 1;            /* So thread 2 doesn't end at once */
  3021.     quitnow = 0;
  3022.     hangnow = 0;
  3023.     termessage[0] = 0;
  3024. #ifdef __32BIT__
  3025.     DosOpenEventSem(NULL, &threadsem);
  3026.     DosResetEventSem(threadsem, &semcount);
  3027.     if (DosCreateThread(&threadid, (PFNTHREAD)rdserwrtscr, 0, 0, THRDSTKSIZ)) {
  3028.     printf("Sorry, can't create thread\n");
  3029.     return (0);
  3030.     }
  3031.     DosWaitEventSem(threadsem, -1L);
  3032. #else
  3033.     DosSemSet(&threadsem);    /* Thread 2 will clear this when it starts */
  3034.     if (DosCreateThread(rdserwrtscr, &threadid,
  3035.             (PBYTE)(stack + THRDSTKSIZ))) {
  3036.     printf("Sorry, can't create thread\n");
  3037.     return (0);
  3038.     }
  3039.     DosSemWait(&threadsem, -1L);/* Wait for thread to start */
  3040.     DosSemSet(&threadsem);    /* Thread 2 will clear this on termination */
  3041. #endif
  3042.  
  3043.     while (active) {        /* Read the keyboard and write to comms line */
  3044.     c = congks(2);
  3045.     if (!active)
  3046.       break;
  3047.     if (c == -1) {
  3048.       active = network || (carrier == CAR_OFF) || (ttgmdm() & BM_DCD) != 0;
  3049.       if (!active)
  3050.         strcpy(termessage, "Carrier lost.\n");
  3051.       continue;
  3052.     }
  3053.     cm = keymap[c];
  3054.     DosEnterCritSec();    /* Protect the run time library */
  3055.     if (cm == escape) {    /* Look for escape char */
  3056.         esc25(0);
  3057.         c = keymap[congks(0)];    /* Got esc, get its arg */
  3058.         if (c == '?') {
  3059.             esc25(1);
  3060.         c = helpconnect(0);
  3061.         }
  3062.         doesc(c);        /* And process it */
  3063.         ipadl25();
  3064.     } else {        /* Ordinary character */
  3065.         if (!keylock)
  3066.         vt100key(c);
  3067.     }
  3068.     DosExitCritSec();    /* Let other guy use run time library */
  3069.     }                /* while (active) */
  3070.  
  3071. #ifdef __32BIT__
  3072.     DosWaitThread(&threadid, 0);
  3073.     DosCloseEventSem(threadsem);
  3074. #else
  3075.     DosSemWait(&threadsem, -1L);/* Wait for other thread to terminate */
  3076. #endif
  3077.  
  3078.     language = langsv;        /* Restore language */
  3079.  
  3080.     concooked();
  3081.     savescreen(&vt100screen);
  3082.     cursoron = TRUE;
  3083.     restorescreen(&commandscreen);
  3084.     restorecursormode();
  3085.     if (termessage[0]!='\0') printf(termessage);
  3086.     if (hangnow) {
  3087. #ifndef NODIAL
  3088.       if (mdmhup() < 1)
  3089. #endif /* NODIAL */
  3090.     tthang();
  3091.     }
  3092.     if (quitnow) doexit(GOOD_EXIT,0);
  3093.     return (1);
  3094. }
  3095.